When calling the same query method twice in a session of the app, I get "DBCommandExcept"
As an experiment, I decided to dispose of the connection object at the end of the method, to see if that was the problem.
I no longer get the DBCommandExcept err msg, but instead get, "the connectionstring property has not been initialized."
IOW, it's sort of a Catch-22 situation at the moment. The pertinent code is:
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: the commented-out block above: When it is active, the DBCommandExcept problem is not seen; however, I then get, "the connectionstring property has not been initialized"
I think the only non-SQL-CE-standard bit above is the dbConn.GetConnection(). Here's some of that code:
SqlCeConnection objCon = null;
. . .
public SqlCeConnection GetConnection()
{
return objCon;
}
private DBConnection() // class constructor
{
try
{
. . .
objCon = new SqlCeConnection(conStr);
objCon.Open();
. . .
Again, the error (either one, whichever one I "choose" to have) is seen only the second time through this method during one run of the app. The first time works fine.
UPDATE
I added the code below, and the comments tell the tale of woe:
// 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();
}
UPDATE 2
Based on unicron's suggestion, I tried using "using."
In two of the three cases (SqlCeCommand and SqlCeDataReader), converting to "using" made no diff; in the other one (SqlCeConnection), it raised the err msgs, "The ConnectionString property has not been initialized."
Still, though, the code is cleaner with the two usings, so thanks for that nudge in the best practices direction.
Here's what it looks like now:
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;
}
}
UPDATE 3
I've come even closer to normalcy by replacing the custom connection code with the generic sort, adding another "using" to the mix:
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;
}
}
...yet I still get "DBCommandExcept"...
As to "stop futzing around with opening the connection," isn't it necessary to do so? How could/should the code above be different?
UPDATE 4
What is even more bizarre is that now my debug log file has stopped being written. I have been writing it out both in the global exception handler AND in the main form's Closed event(), and it always has (until now) at least a few entries, but within the last couple of updates to the code, it is no longer being written...????
Both places global exception handler and main form's Closed event(), the code is like so:
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());
}
}