DB Connection issue only some times - c#

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))
{
...
}

Related

How to manage the mysql connection in correct way without getting a error

I am new to the C# and My method showing a error in try catch connection is already open code as follow, when I closed it from Class method then Form getting a error invalid connection. here if put all code in FORM it is working. but here I get MysqlDataReader as a return value. how can I solve this error.
CLASS
//select all categories
public MySqlDataReader SelectCategory() {
try
{
MySqlCommand cmd = connection.CreateCommand();
cmd.CommandText = "SELECT * FROM categories WHERE online = 1";
connection.Open();
MySqlDataReader categories = cmd.ExecuteReader();
return categories;
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
return null;
}
}
FORM
public void show()
{
MySqlDataReader rd = db.SelectCategory();
try
{
while (rd.Read())
{
listBox1.Items.Add(rd.GetString(1));
}
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}
I would use using which cares about disposing variables and closing connections.
CLASS:
public List<string> SelectCategory()
{
List<string> result = new List<string>();
string Command = "SELECT * FROM categories WHERE online = 1";
using (MySqlConnection mConnection = new MySqlConnection(ConnectionString))
{
mConnection.Open();
using (MySqlCommand cmd = new MySqlCommand(Command, mConnection))
{
using (MySqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
result.Add(reader.GetString(1));
}
}
}
}
return result;
}
FORM:
public void show()
{
try
{
foreach(string item in SelectCategory())
{
listBox1.Items.Add(item);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
The DataReader is an exceptional case used for retrieving data from the database, which always requires an open connection to get values from the DataReader. In your case you are passing the MySqlDataReader to the calling method, So you cannot close the connection from the called method since reader requires the opened connection. so the possibility for you is to Close the connection after closing the DataReader.
Another issue you may face is the connection problem(your current issue), From your code it is clear that you have not closed the connection, so when you call the method for first time, everything will be fine. when the second call triggers the connection's current state will be open so it will throws such exception when you tried to reopen the connection.
Don't worry you can use either one of the following to solve the issue(I'm not sure is such suggestions are valid answers for this community or not, forgive me if not)
Pass your UI control to the class method and Add items to the list
In this case the method is defined inside another class so its not possible to use the UI item there, So better option for is to pass the UI element, the ListBox to that method and make it filled using the reader. For that the code will be like this:
public MySqlDataReader SelectCategory(ListBox listBox1)
{
// fubo's answer here
}
Generate a method for closing connection after checking the connection state, and call that method when while completes its iterations.
The calling method will be like the following:
try
{
using (MySqlDataReader reader = db.SelectCategory())
{
while (reader.Read())
{
listBox1.Items.Add(reader.GetString(1));
}
}
db.CloseConnection(); // will be the method to close the connection
}
use DataTable instead for DataReader :
Get data to a DataTable and then bind the required list using that DataTable
always use finally to close your connection, whatever happen you must close your connection after opening.
public MySqlDataReader SelectCategory() {
try
{
MySqlCommand cmd = connection.CreateCommand();
cmd.CommandText = "SELECT * FROM categories WHERE online = 1";
connection.Open();
MySqlDataReader categories = cmd.ExecuteReader();
return categories;
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
return null;
}
finally
{
if (connection != null && connection.State == ConnectionState.Open)
{
connection.Close();
connection.Dispose();
}
}
}

Passing Connection From TableAdapter Produces connectionstring property has not been initialized

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.

ASP.NET SqlDataReader throwing error: Invalid attempt to call Read when reader is closed

This one has me stumped. Here are the relative bits of code:
public AgencyDetails(Guid AgencyId)
{
try
{
evgStoredProcedure Procedure = new evgStoredProcedure();
Hashtable commandParameters = new Hashtable();
commandParameters.Add("#AgencyId", AgencyId);
SqlDataReader AppReader = Procedure.ExecuteReaderProcedure("evg_getAgencyDetails", commandParameters);
commandParameters.Clear();
//The following line is where the error is thrown. Errormessage: Invalid attempt to call Read when reader is closed.
while (AppReader.Read())
{
AgencyName = AppReader.GetOrdinal("AgencyName").ToString();
AgencyAddress = AppReader.GetOrdinal("AgencyAddress").ToString();
AgencyCity = AppReader.GetOrdinal("AgencyCity").ToString();
AgencyState = AppReader.GetOrdinal("AgencyState").ToString();
AgencyZip = AppReader.GetOrdinal("AgencyZip").ToString();
AgencyPhone = AppReader.GetOrdinal("AgencyPhone").ToString();
AgencyFax = AppReader.GetOrdinal("AgencyFax").ToString();
}
AppReader.Close();
AppReader.Dispose();
}
catch (Exception ex)
{
throw new Exception("AgencyDetails Constructor: " + ex.Message.ToString());
}
}
And the implementation of ExecuteReaderProcedure:
public SqlDataReader ExecuteReaderProcedure(string ProcedureName, Hashtable Parameters)
{
SqlDataReader returnReader;
using (SqlConnection conn = new SqlConnection(connectionString))
{
try
{
SqlCommand cmd = new SqlCommand(ProcedureName, conn);
SqlParameter param = new SqlParameter();
cmd.CommandType = System.Data.CommandType.StoredProcedure;
foreach (DictionaryEntry keyValue in Parameters)
{
cmd.Parameters.AddWithValue(keyValue.Key.ToString(), keyValue.Value);
}
conn.Open();
returnReader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
}
catch (SqlException e)
{
throw new Exception(e.Message.ToString());
}
}
return returnReader;
}
The connection string is working as other stored procedures in the same class run fine. The only problem seems to be when returning SqlDataReaders from this method! They throw the error message in the title. Any ideas are greatly appreciated! Thanks in advance!
A DataReader is generally connected directly to the database. In this case, when you return from the method, you're returning from inside the using statement that created the SqlConnetion object. That will call Dispose on the SqlConnection, and render the SqlDataReader useless.
Try this:
public SqlDataReader ExecuteReaderProcedure(string ProcedureName, Hashtable Parameters)
{
SqlConnection conn = new SqlConnection(connectionString);
using(SqlCommand cmd = new SqlCommand(ProcedureName, conn))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
foreach(DictionaryEntry keyValue in Parameters)
{
cmd.Parameters.AddWithValue(keyValue.Key.ToString(), keyValue.Value);
}
conn.Open();
return cmd.ExecuteReader(CommandBehavior.CloseConnection);
}
}
Call it like this:
public AgencyDetails(Guid AgencyId)
{
evgStoredProcedure Procedure = new evgStoredProcedure();
Hashtable commandParameters = new Hashtable();
commandParameters.Add("#AgencyId", AgencyId);
using(SqlDataReader AppReader =
Procedure.ExecuteReaderProcedure("evg_getAgencyDetails",
commandParameters))
{
commandParameters.Clear();
while(AppReader.Read())
{
AgencyName = AppReader.GetOrdinal("AgencyName").ToString();
AgencyAddress = AppReader.GetOrdinal("AgencyAddress").ToString();
AgencyCity = AppReader.GetOrdinal("AgencyCity").ToString();
AgencyState = AppReader.GetOrdinal("AgencyState").ToString();
AgencyZip = AppReader.GetOrdinal("AgencyZip").ToString();
AgencyPhone = AppReader.GetOrdinal("AgencyPhone").ToString();
AgencyFax = AppReader.GetOrdinal("AgencyFax").ToString();
}
}
}
At the end of the using statement for AppReader, AppReader.Dispose will be called. Since you called ExecuteReader with CommandBehavior.CloseConnection, Disposing of the reader will also close the connection.
Note that I got rid of your bad exception handling as well. Never use ex.Message except possibly for displaying to end-users. Everyone else will want the full exception. Also, no need to print the method name as part of the exception message if you're allowing the full exception to propagate. The method name will be in the stack trace.

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;
}

C# locking away SQLite

I have encountered a problem with getting locked out of SQLite file.
I am currently working on employee register for my company and use SQLite as a database of choice. From my program, I populated the database using scripts I prepared. Reading goes well and all, but once I make any change to the employee at all, the program freezes at "database is locked" exception.
I created a static class called SQLiteManager where I have all methods involving the DB. I then call them from Windows Forms like
foreach (Employee em in SQLiteManager.getEmployees()){
//filling the fields }
calls
public static List<Employee> getEmployees() {
List<Employee> ret = new List<Employee>();
SQLiteDataReader reader;
using (SQLiteConnection dbc = new SQLiteConnection(databaseConnectionString))
using (SQLiteCommand cmd = dbc.CreateCommand())
{
openConnection(dbc);
cmd.CommandText = "select ID_Employee from Employee";
reader = cmd.ExecuteReader();
while (reader.Read()) { ret.Add(extractEmployee(reader["ID_Employee"].ToString(), false)); }
}
return ret;
}
I always use this "using" notations in ALL other methods that call ExecuteReader() in them.
Method that I use to crunch the script and populate the DB:
public static bool processSqlCommandFile(string file)
{
try
{
using (StreamReader sr = new StreamReader(file))
{
string line;
while ((line = sr.ReadLine()) != null)
{
using (SQLiteConnection dbc = new SQLiteConnection(databaseConnectionString))
using (SQLiteCommand cmd = dbc.CreateCommand())
{
openConnection(dbc);
cmd.CommandText = line;
cmd.ExecuteNonQuery();
}
}
sr.Close();
}
}
catch (Exception ex)
{
return false;
}
return true;
}
and finally, the sore method
public static bool alterEmployee(Employee e) {
using (SQLiteConnection dbc = new SQLiteConnection(databaseConnectionString))
using (SQLiteCommand cmd = dbc.CreateCommand())
{
openConnection(dbc);
cmd.CommandText = "Update Employee SET name = '"+e.name+"' where ID_Employee = "+e.id;
//Alter the command once this shiet works
cmd.ExecuteNonQuery();
}
return true;
}
Yet it always gets frozen. By using the using(SQLiteConnection...) I thought I am getting rid of the "sleepy" connections that would somehow lock it, but the trouble is somewhere else.
Can you help me identify the problem or tell me steps to identify it myself?
Thank you

Categories

Resources