title: Why does disposing a SqlCeConnection both solve one exception and raise a different one?
body: <p>When calling the same query method twice in a session of the app, I get "DBCommandExcept"</p>
  
  <p>As an experiment, I decided to dispose of the connection object at the end of the method, to see if that was the problem.</p>
  
  <p>I no longer get the DBCommandExcept err msg, but instead get,  "the connectionstring property has not been initialized."</p>
  
  <p>IOW, it's sort of a Catch-22 situation at the moment. The pertinent code is:</p>
  
  <pre><code>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();
      //}
  }
  </code></pre>
  
  <p>// 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"</p>
  
  <p>I think the only non-SQL-CE-standard bit above is the dbConn.GetConnection(). Here's some of that code:</p>
  
  <pre><code>SqlCeConnection objCon = null; 
  
  . . .
  
  public SqlCeConnection GetConnection()
  {
      return objCon;
  }
  
  
  private DBConnection() // class constructor
  {
      try
      {
          . . .
          objCon = new SqlCeConnection(conStr);
          objCon.Open();
          . . .
  </code></pre>
  
  <p>Again, the error (either one, whichever one I "choose" to have) is seen <em>only the second time</em> through this method during one run of the app. The first time works fine.</p>
  
  <h2>UPDATE</h2>
  
  <p>I added the code below, and the comments tell the tale of woe:</p>
  
  <pre><code>// 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();
  }
  </code></pre>
  
  <h2>UPDATE 2</h2>
  
  <p>Based on unicron's suggestion, I tried using "using."</p>
  
  <p>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, "<em>The ConnectionString property has not been initialized.</em>"</p>
  
  <p>Still, though, the code is cleaner with the two usings, so thanks for that nudge in the best practices direction.</p>
  
  <p>Here's what it looks like now:</p>
  
  <pre><code>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) &amp;&amp; (!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;
      }
  }
  </code></pre>
  
  <h2>UPDATE 3</h2>
  
  <p>I've come even closer to normalcy by replacing the custom connection code with the generic sort, adding another "using" to the mix:</p>
  
  <pre><code>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;
      }
  }
  </code></pre>
  
  <p>...yet I still get "DBCommandExcept"...</p>
  
  <p>As to "stop futzing around with opening the connection," isn't it necessary to do so? How could/should the code above be different?</p>
  
  <h2>UPDATE 4</h2>
  
  <p>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...????</p>
  
  <p>Both places global exception handler and main form's Closed event(), the code is like so:</p>
  
  <pre><code>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());
      }
  }
  </code></pre>