アプリのセッションで同じクエリ メソッドを 2 回呼び出すと、"DBCommandExcept" が発生します。
実験として、メソッドの最後で接続オブジェクトを破棄して、それが問題かどうかを確認することにしました。
DBCommandExcept エラー メッセージは表示されなくなりましたが、代わりに「接続文字列プロパティが初期化されていません」というメッセージが表示されます。
IOW、現時点では一種のキャッチ 22 状況です。関連するコードは次のとおりです。
string query = "SELECT Bla FROM Blah";
SqlCeCommand cmd = new SqlCeCommand(query);
cmd.CommandType = CommandType.Text;
SqlCeConnection conn = dbconn.GetConnection();
cmd.CommandType = CommandType.Text;//probably unnecessary
cmd.Connection = conn;
SqlCeDataReader myReader = cmd.ExecuteReader(CommandBehavior.SingleRow);
try
{
if (myReader.Read())
{
itemID = myReader.GetString(ITEMID_INDEX);
packSize = myReader.GetString(PACKSIZE_INDEX);
recordFound = true;
}
}
catch (Exception ex)
{
RRDR.LogMsgs.Append(string.Format("Exception in PopulateControlsIfVendorItemsFound(): {0}", ex.Message));
}
finally
{
myReader.Close();
//if (null != conn)
//{
// conn.Dispose();
//}
}
// Re: 上記のコメントアウトされたブロック: アクティブな場合、DBCommandExcept の問題は見られません。ただし、「接続文字列プロパティが初期化されていません」というメッセージが表示されます
上記の唯一の非 SQL-CE 標準ビットは dbConn.GetConnection() だと思います。そのコードの一部を次に示します。
SqlCeConnection objCon = null;
. . .
public SqlCeConnection GetConnection()
{
return objCon;
}
private DBConnection() // class constructor
{
try
{
. . .
objCon = new SqlCeConnection(conStr);
objCon.Open();
. . .
繰り返しますが、エラー (私が "選択" したもの) は、アプリの 1 回の実行中にこのメソッドを介して 2 回目にのみ表示されます。初めてはうまくいきます。
アップデート
私は以下のコードを追加しました.コメントは悲惨な話を伝えています:
// With conn check only, still get two consecutive DBCommandExcepts
// With cmd check only, still get two consecutive DBCommandExcepts
// With both, still get two consecutive DBCommandExcepts; IOW, all have the same effect
if (null != conn)
{
conn.Close();
}
if (null != cmd)
{
cmd.Dispose();
}
更新 2
ユニクロンの提案に基づいて、「using」を使用してみました。
3 つのケースのうち 2 つ (SqlCeCommand と SqlCeDataReader) では、"using" に変換しても違いはありませんでした。もう 1 つ (SqlCeConnection) では、「ConnectionString プロパティが初期化されていません。」というエラー メッセージが発生しました。
それでも、コードは 2 つの使用法でよりきれいになっているので、ベスト プラクティスの方向性を示してくれてありがとう。
現在の外観は次のとおりです。
private bool PopulateControlsIfPlatypusItemsFound()
{
const int ITEMID_INDEX = 0;
const int PACKSIZE_INDEX = 1;
bool recordFound = false;
try
{
string PlatypusId = txtPlatypus.Text.ToString().Trim();
string PlatypusItemId = txtUPC.Text.ToString().Trim();
string itemID = string.Empty;
string packSize = string.Empty;
string query = string.Format("SELECT ItemID, PackSize FROM PlatypusItems WHERE PlatypusID = {0} AND PlatypusItemID = {1}", PlatypusId, PlatypusItemId);
using (SqlCeCommand cmd = new SqlCeCommand(query))
{
cmd.CommandType = CommandType.Text;
SqlCeConnection conn = dbconn.GetConnection();
if ((null != conn) && (!conn.State.Equals(ConnectionState.Open)))
{
conn.Open();
TTBT.LogMsgs.Append("Connection opened");
}
cmd.CommandType = CommandType.Text;//probably unnecessary
cmd.Connection = conn;
using (SqlCeDataReader myReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{
if (myReader.Read())
{
itemID = myReader.GetString(ITEMID_INDEX);
packSize = myReader.GetString(PACKSIZE_INDEX);
recordFound = true;
}
}
txtID.Text = itemID;
txtSize.Text = packSize;
return recordFound;
}
}
catch (Exception ex)
{
TTBT.LogMsgs.Append(string.Format("Exception in PopulateControlsIfPlatypusItemsFound: {0} - {1}\r\n", ex.Message, ex.InnerException));
return recordFound;
}
}
更新 3
カスタム接続コードを一般的な並べ替えに置き換え、別の「使用」をミックスに追加することで、正常性にさらに近づきました。
private bool PopulateControlsIfVendorItemsFound()
{
const int ITEMID_INDEX = 0;
const int PACKSIZE_INDEX = 1;
bool recordFound = false;
DUCKBILL.LogMsgs.Append("Made it into frmEntry.PopulateControlsIfVendorItemsFound()\r\n");
try
{
string vendorId = txtVendor.Text.ToString().Trim();
string vendorItemId = txtUPC.Text.ToString().Trim();
string itemID = string.Empty;
string packSize = string.Empty;
if ( dbconn.isValidTable( "VendorItems" ) == -1 )
{
DUCKBILL.LogMsgs.Append("VendorItems not a valid table");//do not see this msg; good! VendorItems is seen as valid...
return false;
}
string query = string.Format("SELECT ItemID, PackSize FROM VendorItems WHERE VendorID = {0} AND VendorItemID = {1}", vendorId, vendorItemId);
using (SqlCeCommand cmd = new SqlCeCommand(query))
{
cmd.CommandType = CommandType.Text;
using (SqlCeConnection conn = new SqlCeConnection())
{
string filename = "\\badPlace2B\\CCRDB.SDF";
conn.ConnectionString = string.Format("Data Source = {0}", filename);
cmd.CommandType = CommandType.Text;//probably unnecessary/moot
cmd.Connection = conn;
conn.Open();
using (SqlCeDataReader myReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{
if (myReader.Read())
{
itemID = myReader.GetString(ITEMID_INDEX);
packSize = myReader.GetString(PACKSIZE_INDEX);
recordFound = true;
}
}
}
txtID.Text = itemID;
txtSize.Text = packSize;
return recordFound;
}
}
catch (Exception ex)
{
DUCKBILL.LogMsgs.Append(string.Format("Exception in PopulateControlsIfVendorItemsFound: {0} - {1}\r\n", ex.Message, ex.InnerException));
return recordFound;
}
}
...まだ「DBCommandExcept」が表示されます...
「コネクションを開いてふざけるのをやめる」ということについては、そうする必要があるのではないでしょうか?上記のコードはどのように異なる可能性がありますか?
更新 4
さらに奇妙なのは、デバッグ ログ ファイルへの書き込みが停止したことです。グローバル例外ハンドラーとメイン フォームの Closed event() の両方に書き込んでおり、常に (今まで) 少なくともいくつかのエントリがありますが、コードの最後の数回の更新では、それはありません。書かれなくなった…????
どちらもグローバル例外ハンドラとメイン フォームの Closed event() を配置します。コードは次のようになります。
public static bool inDebugMode = true;
. . .
if (CCR.inDebugMode)
{
DateTime dt = DateTime.Now;
string timeAsStr = string.Format("{0}_{1}_{2}_{3}.txt", dt.Hour, dt.Minute, dt.Second, dt.Millisecond);
using (StreamWriter file = new StreamWriter(timeAsStr))
{
// If the app closes normally, this is how the file is written; if it doesn't,
// (it crashed) it's written in PDAClient.ExceptionHandler()
file.WriteLine(SSCS.LogMsgs.ToString());
}
}