Passing Connection From TableAdapter Produces connectionstring property has not been initialized - c#

I ran into a problem where passing a connection from a TableAdapter to some methods throws an exception stating the connectionstring isn't initialized. There are quite a few questions on SO with this exception but none were passing the connection and most were because the ConnectionString was null. Weird thing is I used MessageBox.Show(connection.ConnectionString); through out the chain of methods and I receive a valid connection string at every step. This is a somewhat complicated program that is in production but I will try to simplify the code for this question...
This is the postInventoryData method, which takes a DataGridView with inventory items and iterates through it posting them to the inventory. I use a TransactionScope to ensure the changes are safely rolled back in the event of an error. If an item is a kit(an item comprised of other items) I must iterate through those items and remove them from the inventory. The problem occurs when I check whether or not the item is a kit.
public bool postInventoryData(DataGridView dgv)
{
bool successful = true;
TestDataSetTableAdapters.inentoryTrxTableAdapter inventoryTrxAdapter =
new TestDataSetTableAdapters.inentoryTrxTableAdapter();
try
{
using (TransactionScope trxScope = new TransactionScope
(TransactionScopeOption.Required, new System.TimeSpan(0, 15, 0)))
{
MessageBox.Show(inventoryTrxAdapter.Connection.ConnectionString); // <-- Valid ConnectionString
inventoryTrxAdapter.OpenConnection();
for (int i = 0; i < dgv.Rows.Count; i++)
{
//parameter values
string departmentCode = dgv.Rows[i].Cells["Department_Code"].Value.ToString();
string machineCode = dgv.Rows[i].Cells["Machine_Code"].Value.ToString();
string operatorCode = dgv.Rows[i].Cells["Operator_Code"].Value.ToString();
string itemNumber = dgv.Rows[i].Cells["Item_Number"].Value.ToString();
double? qtyProduced = Convert.ToDouble(dgv.Rows[i].Cells["Quantity"].Value.ToString());
bool isKit =
businessLayer.isItemNumberKit
(inventoryTrxAdapter.Connection, itemNumber); // <-- CULPRIT!
// Inserts the item
dailyProductionInsertQty(
departmentCode,
machineCode,
operatorCode,
itemNumber,
isKit,
qtyProduced,
inventoryTrxAdapter,
trxScope);
}
inventoryTrxAdapter.CloseConnection();
trxScope.Complete();
}
}
catch (System.Exception ex)
{
successful = false;
MessageBox.Show(ex.ToString());
}
return successful;
}
The isItemNumberKit method
public bool isItemNumberKit(SqlConnection connection, string itemNumber)
{
bool contains;
MessageBox.Show(connection.ConnectionString); // <-- Valid ConnectionString
DataTable dt = getKit(connection, itemNumber); // <-- CULPRIT!
if (dt.Rows.Count > 0)
{
contains = true;
}
else
{
contains = false;
}
return contains;
}
The getKit method
public DataTable getKit(SqlConnection connection, string itemNumber)
{
DataTable dt = new DataTable();
SqlConnection myConnection = connection;
MessageBox.Show(myConnection.ConnectionString); // <-- Valid ConnectionString
SqlParameter paramItemNumber = new SqlParameter();
paramItemNumber.ParameterName = "#ItemNumber";
paramItemNumber.Value = itemNumber;
paramItemNumber.SqlDbType = System.Data.SqlDbType.VarChar;
try
{
using (myConnection)
{
string sql =
#"SELECT kits.Row_Id,
kits.Kit_Item_Number,
kits.Location_Code
FROM Inventory.dbo.Z_PV_Kits kits
WHERE kits.Kit_Item_Number=#ItemNumber";
//myConnection.Open();
using (SqlCommand myCommand = new SqlCommand(sql, myConnection))
{
myCommand.Parameters.Add(paramItemNumber);
SqlDataReader reader = myCommand.ExecuteReader();
dt.Load(reader);
}
}
}
catch (Exception ex)
{
dt = null;
MessageBox.Show(ex.ToString());
}
return dt;
}
When I execute postInventoryData the program throws an exception with the message, "The connectionstring property has not been initialized." with the line numbers pointing to isItemNumberKit and getKit. As you can see in the code above, I used a MessageBox.Show(connection.ConnectionString) throughout the process and each time I received a valid Connection string. I have created a workaround which stores a cached DataTable containing all the kit items I can run linq statements on. I am not in emergency mode or anything but I thought this to be weird and an opportunity for me to learn. Thanks in advance for any help!

It might be possible that you have 2 app.config files in your solution with 2 different connection strings.

OK, I figured it out and now when I think about it the answer was somewhat obvious. I always use using(){} blocks to ensure connections and similar objects are properly disposed and taken care of after they are used. The solution was to simply remove the using(myConnection){} block from the getKit method like this:
public DataTable getKit(SqlConnection connection, string itemNumber)
{
DataTable dt = new DataTable();
SqlConnection myConnection = connection;
MessageBox.Show(myConnection.ConnectionString);
SqlParameter paramItemNumber = new SqlParameter();
paramItemNumber.ParameterName = "#ItemNumber";
paramItemNumber.Value = itemNumber;
paramItemNumber.SqlDbType = System.Data.SqlDbType.VarChar;
try
{
string sql =
#"SELECT kits.Row_Id,
kits.Kit_Item_Number,
kits.Location_Code
FROM Inventory.dbo.Z_PV_Kits kits
WHERE kits.Kit_Item_Number=#ItemNumber
";
//myConnection.Open();
using (SqlCommand myCommand = new SqlCommand(sql, myConnection))
{
myCommand.Parameters.Add(paramItemNumber);
SqlDataReader reader = myCommand.ExecuteReader();
dt.Load(reader);
}
}
catch (Exception ex)
{
dt = null;
MessageBox.Show(ex.ToString());
}
return dt;
}
This will leave the connection intact but properly dispose of the command. Sorry for the long winded question with a short simple answer. Hope this might help someone someday.

Related

DB Connection issue only some times

I have a problem with the below code,There's no any coding error BUT sometimes it throws some exceptions.I just wanted to know any code organizing issue ? & how to fix it.
Sometimes it shows those exceptions
1.ExecuteReader requires an open and available Connection. The connection's current state is closed.
2.Invalid attempt to call FieldCount when reader is closed.
But Sometimes it works without any issue,as expected
My Coding Goes here
[WebMethod, ScriptMethod]
public static List<HomeImageSliders> GetHomeImageSliders()
{
List<HomeImageSliders> HomeImageList = new List<HomeImageSliders>();
try
{
SqlCommand comHomeImage = new SqlCommand("SP_GetHomeImageSliders", conDB);
comHomeImage.CommandType = CommandType.StoredProcedure;
if (conDB.State != ConnectionState.Open)
{
conDB.Open();
}
SqlDataReader rdr = comHomeImage.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(rdr);
foreach (DataRow r in dt.Rows)
{
HomeImageList.Add(new HomeImageSliders
{
Id = (int)r["Id"],
ImagePath = r["ImagePath"].ToString(),
ModifiedDate = Convert.ToDateTime(r["ModifiedDate"]).Date
});
}
}
catch (Exception ee)
{
}
finally
{
conDB.Close();
}
return HomeImageList;
}
You should use the "using" construction:
(using ommand comHomeImage = new SqlCommand("SP_GetHomeImageSliders", conDB) {
(using SqlDataReader rdr = new SqlDataReader) {
//do some things
}
}
I don't know why your connection sometimes is closed when you call
ExecuteReader()
But why don't you use a using block instead like this:
using(SqlConnection conDB = new SqlConnection(connectionString))
{
...
}
this will close your connection to the DB when it loses scope.
try to prevent using the same connection with two or more threads by usinglock 
lock(_conDb)
{
//// your code here
}
and also wrap your conDb in using block as below
using(SqlConnection conDB = new SqlConnection(connectionString))
{
...
}

How to determine an existing oracle database connection in C#?

Assuming that I call the method below with the right credentials:
private bool Connect(string username, string password)
{
string CONNSTRING = "Provider = MSDAORA; Data Source = ISDQA; User ID = {0}; Password = {1};";
OleDbConnection conn = new OleDbConnection();
string strCon = string.Format(CONNSTRING, username, password);
conn.ConnectionString = strCon;
bool isConnected = false;
try
{
conn.Open();
if (conn.State.ToString() == "Open")
isConnected = true;
}//try
catch (Exception ex)
{
lblErr.Text = "Connection error";
}//catch
finally
{
conn.Close();
}//finally
return isConnected;
}
I have successfully open the connection in my method below:
private bool ValidateUserCode(string usercode)
{
UserAccountDefine def = new UserAccountDefine();
UserAccountService srvc = new UserAccountService();
UserAccountObj obj = new UserAccountObj();
bool returnVal = false;
bool isValid = Connect(def.DB_DUMMY_USERCODE, def.DB_DUMMY_PASSWORD);
if (isValid)
{
obj.SQLQuery = string.Format(def.SQL_LOGIN, usercode.ToLower(), DateTime.Now.ToString("MM/dd/yyy"));
DataTable dt = srvc.Execute(obj, CRUD.READALL);
if (dt.Rows.Count == 1)
{
returnVal = true;
}
}
return returnVal;
}
The question is how can I determine the connection status in ValidateUserCode() method?
How can I close it afterwards?
Note:
I explicitly declare the string variables in UserAccountDefine(); so you don't have to worry about that.
I already tried declaring a new OleDbConnection conn inside the ValidateUserCode() to but the conn.State always returning "Closed".
UPDATE
I have a system with 2-layer security feature. 1st is in application and 2nd is on database. If a user logs in to the application, the username and password is also used to log him/her in to the database. Now, the scenario is when a user forgot his/her password, we can't determine the fullname, email and contact (which are maintained in the database) of the user. I just know his usercode. To determine the contact details, I have to open an active connection using a DUMMY_ACCOUNT.
Note that I never maintain the password inside the database.
First of all, you call Close() in your finally block, which means that at any point in your second method, the connection would be closed. Moreover, even if you don't Close() it,since conn is a local variable in Connect(), when you're back in ValidateUserCode(), the connection is already up for garbage collection, and when it's Dispose()d, it also closes automatically.
I sugges you either make it a member, pass it as an out parameter, return it by the Connect() method (and return null for failure, or something, if you don't like exceptions)..or redesign the code.
private OleDbConnection Connect(string username, string password)
{
string CONNSTRING = "Provider = MSDAORA; Data Source = ISDQA; User ID = {0}; Password = {1};";
OleDbConnection conn = new OleDbConnection();
string strCon = string.Format(CONNSTRING, username, password);
conn.ConnectionString = strCon;
try
{
conn.Open();
if (conn.State.ToString() == "Open")
return conn;
}//try
catch (Exception ex)
{
lblErr.Text = "Connection error";
}//catch
finally
{
//you don't want to close it here
//conn.Close();
}//finally
return null;
}
I am not sure how this information helps you.
I had similar problem while using OLEDB connection for Excel Reading. I didn't knew the answer. So, just I added a global variable for OleDbConnection initialized to null.
In my method, I used to check that null, if not close it and again open it.
if (con != null)
{
con.Close();
con.Dispose();
}
try
{
con = new OleDbConnection(connectionString);
}
catch (Exception ex)
{
MessageBox.Show("oledbConnection = " + ex.Message);
}
try
{
con.Open();
}
catch (Exception ex)
{
MessageBox.Show("connection open = " + ex.Message + "\n");
}
I could able to continue after this. You can try, if it works for you its good!
I'm not sure I follow the question quite right. My answer is based on the premise that you want to open/retrieve a connection, take an action, and close/release the connection afterward.
The code you include does not do that well. Typical DAO code resembles this pseudocode, in my case taken from some boilerplate code I use.
public DataSet FetchDataSet(string sql, IDictionary paramHash) {
var cnn = AcquireConnection();
var rtnDS = new DataSet();
try
{
var cmd = cnn.CreateCommand();
cmd.CommandText = sql;
SetParameters(cmd, paramHash);
IDbDataAdapter ida = new DataAdapter { SelectCommand = cmd };
LogSql(sql, paramHash, "FetchDataSet");
ida.Fill(rtnDS);
}
catch (Exception ex)
{
DebugWriteLn("Failed to get a value from the db.", ex);
throw;
}
finally
{
ReleaseConnection(cnn);
}
return rtnDS;
}
Note that the code above is strictly about communicating with the database. There is no assessment of whether the data is right or wrong. You might have a DAO that is a subclass of the one that contains the above code, and it might do this:
public MyItemType FindSomeValue(long Id)
{
const string sql = #"SELECT something from somewhere where id=:id";
var myParams = new Dictionary<string, long> { { "id", Id } };
var ds = FetchDataSet(sql, myParams);
return (from DataRow row in ds.Tables[0].Rows
select new Item
{
Id = Convert.ToInt64(row["ID"], CultureInfo.InvariantCulture),
Name = row["NAME"].ToString()
}).FirstOrDefault();
}
In fact, the above is pseudocode from a DAO implementation that I've used for years. It makes data access relatively painless. Note that there is some real code behind those methods like SetParameters (30 - 80 lines or so), and I have a bunch of other protected methods like FetchScalar, ExecuteSQL, etc.

Why does disposing a SqlCeConnection both solve one exception and raise a different one?

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());
}
}
Since you are making several calls to a database file (that isn't going to change), I'd start out by defining your connection string and your SQL statements at the top of your class as global values:
private const int ITEMID_INDEX = 0;
private const int PACKSIZE_INDEX = 1;
private const string SQL_CONN_STR = "Data Source=\\badPlace2B\\CCRDB.SDF";
private const string SQL_GET_VENDOR_ITEMS = "SELECT ItemID, PackSize " +
"FROM VendorItems " +
"WHERE VendorID=#VendorID AND VendorItemID=#VendorItemID";
These never change, so there is no reason to define them again each time you call your routine.
Personally, I do not like inserting values into SQL statements, like you have shown. Rather, try to use Parameters.
To use Parameters, you'll need to look into your database to see what type of columns VendorID and VendorItemID are. My guess is that they are both int values, but these could be GUID like values, requiring VarChar type strings. If these are strings, you should write down what sizes the columns are defined as.
For example: Below, my Serial_Number column is the SqlDbType.NVarChar and the size is 50. An SqlCeParameter for this column would be:
cmd.Parameters.Add("#Serial_Number", SqlDbType.NVarChar, 50).Value = txtSerial_Number.Text.Trim();
Since I did not know what type of data you use, I created an enumerated type to show how each method would be used. If you do not have access to the table's design, the last resort is "AddWithValue" (I personally hate that one, because it makes me look like I don't know what my database has inside).
enum ParamStyle { AddWithValue, AddIntegers, AddVarChar }
To use this enumerated type, I modified the signature of your method to pass in that value:
private bool PopulateControlsIfVendorItemsFound(ParamStyle style) {
Obviously, you will not need this, because you should know what technique you are going to be coding with.
I wasn't able to figure out what your dbconn object was. Initially, I thought this was your SqlCeConnection, but that does not have an isValidTable method, so I just commented it out:
//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;
//}
Speaking of SqlCeConnection...
I combined your SqlCeCommand instance with your SqlCeConnection instance. Less code typically means fewer errors:
using (var cmd = new SqlCeCommand(SQL_GET_VENDOR_ITEMS, new SqlCeConnection(SQL_CONN_STR))) {
The CommandType, by default, is CommandType.Text, so this line is unnecessary:
// cmd.CommandType = CommandType.Text; (this is the default)
I moved most of your variable reading outside of the try/catch routine, as none of that should ever cause an exception to be generated.
Also, I used the more targeted SqlCeException instead of the general Exception. The only thing that could fail in the block is something SqlCe related, and the SqlCeException will give you better/more specific error messages than the general Exception object will.
} catch (SqlCeException err) {
So, what does it look like all put together?
Code:
enum ParamStyle { AddWithValue, AddIntegers, AddVarChar }
private const int ITEMID_INDEX = 0;
private const int PACKSIZE_INDEX = 1;
private const string SQL_CONN_STR = "Data Source=\\badPlace2B\\CCRDB.SDF";
private const string SQL_GET_VENDOR_ITEMS = "SELECT ItemID, PackSize FROM VendorItems WHERE VendorID=#VendorID AND VendorItemID=#VendorItemID";
private bool PopulateControlsIfVendorItemsFound(ParamStyle style) {
bool recordFound = false;
//DUCKBILL.LogMsgs.Append("Made it into frmEntry.PopulateControlsIfVendorItemsFound()\r\n");
string itemID = null;
string packSize = null;
//string vendorId = txtVendor.Text.Trim();
//string vendorItemId = txtUPC.Text.Trim();
//string query = string.Format("SELECT ItemID, PackSize FROM VendorItems WHERE VendorID = {0} AND VendorItemID = {1}", vendorId, vendorItemId);
//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;
//}
using (var cmd = new SqlCeCommand(SQL_GET_VENDOR_ITEMS, new SqlCeConnection(SQL_CONN_STR))) {
// cmd.CommandType = CommandType.Text; (this is the default)
if (style == ParamStyle.AddIntegers) { // Adding Integers:
cmd.Parameters.Add("#VendorID", SqlDbType.Int).Value = Convert.ToInt32(txtVendor.Text.Trim());
cmd.Parameters.Add("#VendorItemID", SqlDbType.Int).Value = Convert.ToInt32(txtUPC.Text.Trim());
} else if (style == ParamStyle.AddVarChar) { // Adding String Values
// NOTE: Here, you should look in your database table and
// use the size you defined for your VendorID and VendorItemID columns.
cmd.Parameters.Add("#VendorID", SqlDbType.VarChar, 25).Value = txtVendor.Text.Trim();
cmd.Parameters.Add("#VendorItemID", SqlDbType.VarChar, 50).Value = txtUPC.Text.Trim();
} else if (style == ParamStyle.AddWithValue) { // Adding as Objects (only if you don't know what the data types are)
cmd.Parameters.AddWithValue("#VendorID", txtVendor.Text.Trim());
cmd.Parameters.AddWithValue("#VendorItemID", txtUPC.Text.Trim());
}
try {
cmd.Connection.Open();
using (var myReader = cmd.ExecuteReader(CommandBehavior.SingleRow)) {
if (myReader.Read()) {
itemID = myReader.GetString(ITEMID_INDEX);
packSize = myReader.GetString(PACKSIZE_INDEX);
recordFound = true;
}
}
} catch (SqlCeException err) {
//DUCKBILL.LogMsgs.Append(string.Format("Exception in PopulateControlsIfVendorItemsFound: {0}\r\n", err.Message));
// (I never return from a 'catch' statement) return recordFound;
} finally {
if (cmd.Connection.State == ConnectionState.Open) {
cmd.Connection.Close();
}
}
}
if (recordFound) { // set these last, and set them OUTSIDE of the try/catch block
txtID.Text = itemID;
txtSize.Text = packSize;
}
return recordFound;
}
Happy Coding!

Object reference not set to an instance of object

I have a function like this
public void GetTablesWithUpperCaseName()
{
SqlConnectionStringBuilder objConnectionString = new SqlConnectionStringBuilder();
objConnectionString.DataSource = txtHost.Text;
objConnectionString.UserID = txtUsername.Text;
objConnectionString.Password = txtPassword.Text;
objConnectionString.InitialCatalog = Convert.ToString(cmbDatabases.SelectedValue);
SqlConnection sConnection = new SqlConnection(objConnectionString.ConnectionString);
//To Open the connection.
sConnection.Open();
//Query to select table_names that have their names in uppercase letters.
string selectTablesWithUppercaseName = #"SELECT
NAME
FROM
sysobjects
WHERE
UPPER(name) COLLATE Latin1_General_BIN = name COLLATE Latin1_General_BIN
AND
OBJECTPROPERTY(ID,N'IsTable')=1
AND
OBJECTPROPERTY(ID,N'IsMSShipped')=0 ";
//Create the command object
SqlCommand sCommand = new SqlCommand(selectTablesWithUppercaseName, sConnection);
try
{
//Create the dataset
DataSet dsListOfTablesWithUppercaseName = new DataSet("sysobjects");
//Create the dataadapter object
SqlDataAdapter sDataAdapter = new SqlDataAdapter(selectTablesWithUppercaseName, sConnection);
//Provides the master mapping between the sourcr table and system.data.datatable
sDataAdapter.TableMappings.Add("Table", "sysobjects");
//Fill the dataset
sDataAdapter.Fill(dsListOfTablesWithUppercaseName);
//Bind the result combobox with foreign key table names
DataViewManager dvmListOfForeignKeys = dsListOfTablesWithUppercaseName.DefaultViewManager;
dgResultView.DataSource = dsListOfTablesWithUppercaseName.Tables["sysobjects"];
}
catch(Exception ex)
{
//All the exceptions are handled and written in the EventLog.
EventLog log = new EventLog("Application");
log.Source = "MFDBAnalyser";
log.WriteEntry(ex.Message);
}
finally
{
//If connection is not closed then close the connection
if(sConnection.State != ConnectionState.Closed)
{
sConnection.Close();
}
}
}
And another function for counting the rows generated from the previous functions. But this function
Null Reference Exception or Object
reference not set to an instance of
object..
Can anyone help me in this... why it is catching error only for the functions above and working fine for all other similar functions.
private void UpdateLabelText()
{
SqlConnectionStringBuilder objConnectionString = new SqlConnectionStringBuilder();
objConnectionString.DataSource = txtHost.Text;
objConnectionString.UserID = txtUsername.Text;
objConnectionString.Password = txtPassword.Text;
objConnectionString.InitialCatalog = Convert.ToString(cmbDatabases.SelectedValue);
SqlConnection sConnection = new SqlConnection(objConnectionString.ConnectionString);
//To Open the connection.
sConnection.Open();
try
{
int SelectedCellTotal = 0;
int counter;
// Iterate through the SelectedCells collection and sum up the values.
for(counter = 0;counter < (dgResultView.SelectedCells.Count);counter++)
{
if(dgResultView.SelectedCells[counter].FormattedValueType == Type.GetType("System.String"))
{
string value = null;
// If the cell contains a value that has not been commited,
if(dgResultView.IsCurrentCellDirty == true)
{
value = dgResultView.SelectedCells[counter].EditedFormattedValue.ToString();
}
else
{
value = dgResultView.SelectedCells[counter].FormattedValue.ToString();
}
if(value != null)
{
// Ignore cells in the Description column.
if(dgResultView.SelectedCells[counter].ColumnIndex != dgResultView.Columns["TABLE_NAME"].Index)
{
if(value.Length != 0)
{
SelectedCellTotal += int.Parse(value);
}
}
}
}
}
// Set the labels to reflect the current state of the DataGridView.
lblDisplay.Text = "There are Total " + dgResultView.RowCount + cmbOperations.SelectedItem.ToString();
}
catch(Exception ex)
{
//All the exceptions are handled and written in the EventLog.
EventLog log = new EventLog("Application");
log.Source = "MFDBAnalyser";
log.WriteEntry(ex.Message);
}
finally
{
//If connection is not closed then close the connection
if(sConnection.State != ConnectionState.Closed)
{
sConnection.Close();
}
}
}
Also the lblDisplay.Text is not taking proper spaces.
Waiting for reply
OK, I don't really have an answer why you're getting a "null reference exception" - but a few points to throw in, nonetheless:
I would use sys.tables instead of sysobjects and having to specify what type of object to query for
ALWAYS put your disposable SqlConnection and SqlCommand into using(.....) { ...... } blocks. That way, you won't need any finally {..} blocks, and .NET will take care of properly disposing of those objects when they're no longer needed
why do you use a DataSet when you only have a single table inside?? That's just unnecessary overhead - use a DataTable instead!
don't open the SqlConnection that early - wait 'til the very last moment, open it, execute query, close it again right away
actually, when using the SqlDataAdapter, you don't need to open the SqlConnection yourself at all - the SqlDataAdapter will do that for you (and close it again after it is done reading the data)
do not mix the retrieval of the data from the database with the binding to the UI element - this is a very bad practice. From the GetTablesWithUpperCaseName method, you should return something (like a DataTable) to the caller (the UI) and let the UI handle the binding process
along the same lines: that method should not be grabbing stuff from UI elements (like text boxes) itself - pass in those values as method parameters, to get a cleaner code - one that you might actually be able to reuse in another project some day
This is how I think your first method ought to look like
public DataTable GetTablesWithUpperCaseName(string server, string database,
string username, string password)
{
// Create the datatable
DataTable dtListOfTablesWithUppercaseName = new DataTable("tableNames");
SqlConnectionStringBuilder objConnectionString = new SqlConnectionStringBuilder();
objConnectionString.DataSource = server;;
objConnectionString.UserID = username;
objConnectionString.Password = password;
objConnectionString.InitialCatalog = database;
// Define the Query against sys.tables - much easier and cleaner!
string selectTablesWithUppercaseName =
"SELECT NAME FROM sys.tables WHERE UPPER(name) COLLATE Latin1_General_BIN = name COLLATE Latin1_General_BIN AND is_msshipped = 0";
// put your SqlConnection and SqlCommand into using blocks!
using (SqlConnection sConnection = new SqlConnection(objConnectionString.ConnectionString))
using (SqlCommand sCommand = new SqlCommand(selectTablesWithUppercaseName, sConnection))
{
try
{
// Create the dataadapter object
SqlDataAdapter sDataAdapter = new SqlDataAdapter(selectTablesWithUppercaseName, sConnection);
// Fill the datatable - no need to open the connection, the SqlDataAdapter will do that all by itself
// (and also close it again after it is done)
sDataAdapter.Fill(dtListOfTablesWithUppercaseName);
}
catch (Exception ex)
{
//All the exceptions are handled and written in the EventLog.
EventLog log = new EventLog("Application");
log.Source = "MFDBAnalyser";
log.WriteEntry(ex.Message);
}
}
// return the data table to the caller
return dtListOfTablesWithUppercaseName;
}

Using SqlDataReader to fill an ArrayList?

I'm trying to implement a method which will take a given connection string and return an ArrayList containing the contents of a SQL view.
I've verified the validity of the connection string and the view itself. However I don't see what the problem is in the code below. In debug, when it runs the ExecuteReader method and then try to enter the while loop to iterate through the records in the view, it immediately bails because for some reason sqlReader.Read() doesn't.
public ArrayList GetEligibles(string sConnectionString)
{
string sSQLCommand = "SELECT field1, field2 FROM ViewEligible";
ArrayList alEligible = new ArrayList();
using (SqlConnection sConn = new SqlConnection(sConnectionString))
{
// Open connection.
sConn.Open();
// Define the command.
SqlCommand sCmd = new SqlCommand(sSQLCommand, sConn);
// Execute the reader.
SqlDataReader sqlReader = sCmd.ExecuteReader(CommandBehavior.CloseConnection);
// Loop through data reader to add items to the array.
while (sqlReader.Read())
{
EligibleClass Person = new EligibleClass();
Person.field1 = sqlReader["field1"].ToString();
Person.field2 = sqlReader["field2"].ToString();
alEligible.Add(Person);
}
// Call Close when done reading.
sqlReader.Close();
}
return alEligible;
}
Note, EligibleClass is just a class object representing one row of the view's results.
A couple of things I would check:
Is the connection string ok
Does the user in your connection string have access to the database/view
Can you access that database from the pc your at
Does the ViewEligable view exist
Does the view contain a field1 and field2 column.
Here one way you could possibly clean up that code somewhat (assuming you have .net 2.0)
public List<EligibleClass> GetEligibles(string sConnectionString)
{
List<EligibleClass> alEligible = null;
try
{
using (SqlConnection sConn = new SqlConnection(sConnectionString))
{
sConn.Open();
using (SqlCommand sCmd = new SqlCommand())
{
sCmd.Connection = sConn;
sCmd.CommandText = "SELECT field1, field2 FROM ViewEligible";
using (SqlDataReader sqlReader = sCmd.ExecuteReader())
{
while (sqlReader.Read())
{
EligibleClass Person = new EligibleClass();
Person.field1 = sqlReader.GetString(0);
Person.field2 = sqlReader.GetString(1);
if (alEligible == null) alEligible = new List<EligibleClass>();
alEligible.Add(Person);
}
}
}
}
}
catch (Exception ex)
{
// do something.
}
return alEligible;
}

Categories

Resources