Correct SqlConnection declaration - c#

The problem is that I have used my SqlConnection as a public static connection, thinking this might be the problem causing form time to time an error :
*the connection is not open or the connection was already open
So is it ok to use one statement of SqlConnection in a static class?
So that I could Declare it only once, I know I could use connectionString in web.config
ConfigurationManager.ConnectionStrings["conn"].ConnectionString ...
but I like it to stay unrelated to web.config settings or servers name.
ReEdit :
as it is realy two methods within same class theres also another class in that main class
but this is not what's important rather than using same connection for all
executions ! so you say that even though i re edited with right code of my helprer class
this is wrong ?
public static class myDBhelper
{
public static SqlConnection Conn = new SqlConnection ("server=(local);Initial Catalog=dbName;Integrated Security=True");
public static int ExecSQLint(string TblintSQL)
{
int anIntValue=0;
SqlCommand TblintCMD = new SqlCommand(TblintSQL, Conn);
try
{
Conn.Open();
anIntValue = Convert.ToInt32(TblintCMD.ExecuteScalar());
}
catch (System.Data.SqlClient.SqlException ex)
{
throw new Exception("No Can Do: " + ex.Message);
}
finally
{
Conn.Close();
}
return anIntValue;
}
public static string ExecSQLstring(string TblStrSQL)
{
string strValue="";
SqlCommand TblStrCMD = new SqlCommand(TblStrSQL, Conn);
try
{
Conn.Open();
strValue = TblStrCMD.ExecuteScalar().ToString();
}
catch (System.Data.SqlClient.SqlException ex)
{
throw new Exception("No Can Do: " + ex.Message);
}
finally
{
Conn.Close();
}
return strValue;
}
}
The main issue I suspect is those two options :
SqlConnection Conn = new SqlConnection("Data Source=(local);Integrated Security=True;database=dbName")
in my DBhelper class I was using this declaration
SqlConnection Conn = new SqlConnection("server=(local);Initial Catalog=dbName;Integrated Security=True");
could that be unstable or error prone ?
p.s.: I am executing commands via try catch
try
{
Conn.Open();
cmd.ExecuteNonQuery();
}
catch (System.Data.SqlClient.SqlException ex)
{
throw new Exception("No Can Do: " + ex.Message);
}
finally
{
Conn.Close();
}
Is Using statement more appropriate? Although it is not my problem I was thinking... if I am already trying to do it 'by the book'...
Is any method here actually wrong among those ?

Keeping Connection as static is not a common way to use connection to database. It could lead to exception as you mentioned when application is working on web or multi-thread environment.
Image that thread 1 executing command 1 is the same connection with thread 2 executing command 2. Your ex: TblintCMD and TblStrCMD. When thread 1 finishs, it closed connection, meanwhile thread 2 is still executing command on close connection
Your two options are not the problem.
The best way is to use using keyword and create connection when needed:
using (var connection = new SqlConnection("yourConnectionString"))
{
connection.Open();
...
}
using is similar with:
var connection = new SqlConnection("connectionString");
try
{
connection.Open();
....
}
finally
{
connection.Close();
}
So, you don't need to know when to close Connection.
Behind the scene, ADO.NET uses connection pool to manage connections for you automatically, so you should not care much how many connections open.

using(var conn=new. SqlConnection( "server=(local);Initial Catalog=dbName;Integrated Security=True"))
{
conn.Open();
}

public SqlConnection GetSqlConnection()
{
SqlConnection sql = new SqlConnection();
sql.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["SchoolContext"].ToString();
return sql;
}

Related

How to insert data quickly into SQL Server using a stored procedure

I have an application in C# which receives data from different clients and insert that data into SQL Server. I get the data every second, or even faster, but I am facing some problem with my code:
static SqlConnection objSqlConn = null;
static SqlCommand objSqlCmd = null;
public static void SaveClientHistory(String strMessage, String strClientIP)
{
try
{
using (objSqlConn = new SqlConnection(strConnectionString))
{
using (objSqlCmd = new SqlCommand("procInsertHistory", objSqlConn))
{
objSqlCmd.CommandTimeout = 0;
objSqlCmd.CommandType = CommandType.StoredProcedure;
objSqlCmd.Parameters.AddWithValue("#strMessage", strMessage);
objSqlCmd.Parameters.AddWithValue("#strClientIP", strClientIP);
objSqlConn.Open();
objSqlCmd.ExecuteNonQuery();
}
}
}
catch (Exception Ex)
{
throw Ex;
}
finally
{
if(objSqlConn != null && objSqlConn.State != ConnectionState.Closed)
{
objSqlConn.Close();
objSqlConn.Dispose();
}
}
}
Different types of exceptions occurred:
The connection was not closed. The connection's current state is connecting.
Internal connection fatal error.
ExecuteNonQuery requires an open and available Connection. The connection's current state is connecting.
Please, advise me if there is any error in above code or suggest any other way to accomplish this task.
Thanks
Edited - simplified the procedure further to better troubleshoot the issue: removed the try/catch because it wasn't doing anything helpful; method is no longer static; all inputs are now passed in as parameters - including strConnectionString; the connection timeout is explicitly set; the connection is opened before the SqlCommand object is instantiated; the command timeout is now 10 seconds.
As performance is a concern of yours, note that you should not be worried about trying to keep a connection open for re-use. By default, SQL Server connection pooling is turned on, so there is no need to attempt to cache connections with your own methodology.
There seems like there is something going on besides attempting to open a connection and executing a non-query, so I tried to simplify your code a little further. I hope it helps with troubleshooting your issue.
public int SaveClientHistory(String strConnectionString, String strMessage, String strClientIP)
{
// You can double-up using statements like this (for slightly better readability)
using (SqlConnection objSqlConn = new SqlConnection(strConnectionString))
{
objSqlConn.ConnectionTimeout = 10; // Creating a connection times out after ten seconds
objSqlConn.Open();
using (SqlCommand objSqlCmd = new SqlCommand("procInsertHistory", objSqlConn))
{
objSqlCmd.CommandTimeout = 10; // Creating a command times out after ten seconds
objSqlCmd.CommandType = CommandType.StoredProcedure;
objSqlCmd.Parameters.AddWithValue("#strMessage", strMessage);
objSqlCmd.Parameters.AddWithValue("#strClientIP", strClientIP);
return objSqlCmd.ExecuteNonQuery();
}
}
}
It seems that all three errors are related with connection. In one of my applications, I implement you function like bellow. I hope this help you:
public static void SaveClientHistory(String strMessage, String strClientIP)
{
SqlConnection objSqlConn = new SqlConnection(strConnectionString);
SqlCommand objSqlCmd = new SqlCommand("procInsertHistory", objSqlConn)
objSqlCmd.CommandType = CommandType.StoredProcedure;
objSqlCmd.Parameters.AddWithValue("#strMessage", strMessage);
objSqlCmd.Parameters.AddWithValue("#strClientIP", strClientIP);
try{
objSqlConn.Open();
objSqlCmd.ExecuteNonQuery();
}
catch (Exception Ex)
{
throw Ex;
}
finally
{
if(objSqlConn.State == ConnectionState.Open)
objSqlConn.Close();
}
}

Connection does not close like it should

I am encountering the following error in my ASP project:
The connection was not closed. The connection's current state is open
While calling the .open() function on a SqlConnection Object.
I have tried this :
if (Conn.State != ConnectionState.Closed)
{
Log.Message(xxx);
try
{
Conn.Close();
}
catch (Exception ex)
{
Log.Error(xxxx);
}
}
Conn.Open();
But this still raises the error. The Conn object is declared as:
private static readonly SqlConnection Conn = new SqlConnection(xxxx);
Any idea where I should look for a solution
Here's the pattern.
using(var conn = new SqlConnection(connectionString))
using(var cmd = new SqlCommand(someSql, conn)
{
conn.Open();
cmd.ExecuteNonQueryOrWhatevs();
}
Create your connection
Open your connection
Dispose of your connection
Don't try to reuse it. Just get it, use it, and dispose of it as fast as possible.
Also, none of this is thread safe, so don't be touching any of the above instances from different threads. One thread to use the connection only, please. Feel free to use multiple threads to process the results.
To ensure that connections are always closed, open the connection inside of a using block, as shown in the following code fragment. Doing so ensures that the connection is automatically closed when the code exits the block.
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
// Do work here; connection closed on following line.
}
The best way to close the connection and disposed object is 'Finally' you should go for it.
OR better to use Using to dispose all objects and close connections see below snippet
public void run_runcommand(string query)
{
using(var con = new SqlConnection(connectionString))
{
using(var cmd = new SqlCommand(query, con))
{
con.Open();
// ...
}
} // close not needed since dispose also closes the connection
}

How to work with many connection in c# and ASP.NET?

This is how I do my connection
SqlConnection conn = new SqlConnection(connectionstring);
conn.open();
SqlCommand comando = new SqlCommand(/*my query update/delete/insert/select o execute sp*/,conn);
comando.Parameters.Add("#parameter1","value1")
comando.Parameters.Add("#parameter2","value2")
comando.Parameters.Add("#parameterN","valueN")
comando.ExecuteNonQuery()
conn.close();
but server administrator says there are many connections.
Then, how can I execute my queries?
Would it be better if I do not close the connection?
No, it would not be better to leave the connection open. Use "using" commands to manage system resources.
using(SqlConnection conn = new SqlConnection(stringconection))
{
conn.Open();
SqlCommand comando = new SqlCommand(/*my query update/delete/insert/select o execute sp*/,conn);
comando.Parameters.Add("#parameter1","value1");
comando.Parameters.Add("#parameter2","value2");
comando.Parameters.Add("#parameterN","valueN");
comando.ExecuteNonQuery();
}
Here is a quote from the documentation:
It is recommended that you always close the Connection when you are finished using it in order for the connection to be returned to the pool. This can be done using either the Close or Dispose methods of the Connection object. Connections that are not explicitly closed might not be added or returned to the pool. For example, a connection that has gone out of scope but that has not been explicitly closed will only be returned to the connection pool if the maximum pool size has been reached and the connection is still valid.
You can use "using" like Mark mentioned above (my preference). You can also use a try-catch-finally block.
try
{
SqlConnection conn = new SqlConnection(stringconection);
conn.Open();
SqlCommand comando = new SqlCommand(/*my query update/delete/insert/select o execute sp*/,conn);
comando.Parameters.Add("#parameter1","value1");
comando.Parameters.Add("#parameter2","value2");
comando.Parameters.Add("#parameterN","valueN");
comando.ExecuteNonQuery();
}
catch(Exception ex)
{
// catch exceptions here
}
finally
{
if(comando != null)
{
comando.Dispose();
}
if(conn != null)
{
conn.Dispose();
}
}

Application Crash on SQL Connection.Close method

I have a windows services which is performing lot of Data processing. At some point, my service is crashed on closing a SQLConnection. When I comment the Close connection method call, Service is working consistently without crashing.
What could be the problem ? Below is a code snippet
private void DeleteTempTable()
{
_logger.Info("DeleteTempTable");
try
{
foreach (KeyValuePair<string, string> item in _stables)
{
string dropSql = string.Empty;
dropSql = string.Format("DROP TABLE [{0}];", item.Value);
SqlConnection oConnDropTables = new SqlConnection(connectionString);
oConnDropTables.Open();
if (!string.IsNullOrEmpty(dropSql))
{
using (SqlCommand cmd = new SqlCommand(dropSql, oConnDropTables))
{
cmd.ExecuteNonQuery();
}
}
if (oConnDropTables != null && oConnDropTables.State == ConnectionState.Open)
oConnDropTables.Close();
oConnDropTables = null;
}
}
catch (Exception ex)
{
_logger.Error("Error " + ex.Message);
throw ex;
}
}
When I comment the Close connection, service is working without crashing. Also it is not caught in the catch block. Also Connection is not Null and connectionstate is open only..
What I have tried:
1) Put "using" construct for connection - Didn't help
2) catching SQLException to check if anything I get- Didn't help
Removing that Close() should not make any problems go away, and frankly I don't believe it has. Since you don't yet understand the problem, it is premature to assume that a random code change has fixed it. Specifically:
with the Close(), it is returning the connection to the pool each time; when you call Open(), it will get back the same connection from the pool (cleansed, except for a few minor things)
without the Close(), the previous connection will be left to be garbage collected, which can cause either the connection-pool to become saturated, or the database-server's connection count to saturate; basically - bad things
What I suspect is happening is that you had some random error, that you now aren't seeing, by random. For example, network connectivity, or the unpredictable ordering of a Dictionary<,> (which means you don't know what order the tables are being DROPped, which is very important if there are foreign keys between them).
The only major problem with the current code is that it isn't using using. There are some redundant lines, though. This would be better:
foreach (var item in _stables)
{
var dropSql = string.Format("DROP TABLE [{0}];", item.Value);
using(var oConnDropTables = new SqlConnection(connectionString))
using (var cmd = new SqlCommand(dropSql, oConnDropTables))
{
oConnDropTables.Open();
cmd.ExecuteNonQuery();
}
}
or (preferable):
using(var oConnDropTables = new SqlConnection(connectionString))
{
oConnDropTables.Open();
foreach (var item in _stables)
{
var dropSql = string.Format("DROP TABLE [{0}];", item.Value);
using (var cmd = new SqlCommand(dropSql, oConnDropTables))
{
cmd.ExecuteNonQuery();
}
}
}
The issue is the creation of a new connection object each time the loop runs. When you close a SQL Connection, it is not actually closed but its returned to the app pool ready to be re-used. There is a limited number of connections you can open in SQL at once.
Try moving the SQLConnection object out of the loop and just execute commands in the loop and close the connection after the loop finishes.
private void DeleteTempTable()
{
_logger.Info("DeleteTempTable");
try
{
using(SqlConnection oConnDropTables = new SqlConnection(connectionString))
{
oConnDropTables.Open();
foreach (KeyValuePair<string, string> item in _stables)
{
string dropSql = string.Empty;
dropSql = string.Format("DROP TABLE [{0}];", item.Value);
if (!string.IsNullOrEmpty(dropSql))
{
using (SqlCommand cmd = new SqlCommand(dropSql, oConnDropTables))
{
cmd.ExecuteNonQuery();
}
}
}
}
}
catch (Exception ex)
{
_logger.Error("Error " + ex.Message);
throw ex;
}
}

Retrying method to call database

Im making a system which should be running 24/7, with timers to control it. There are many calls to the database, and at some point, two methods are trying to open a connection, and one of them will fail. I've tried to make a retry method, so my methods would succeed. With the help from Michael S. Scherotter and Steven Sudit's methods in Better way to write retry logic without goto, does my method look like this:
int MaxRetries = 3;
Product pro = new Product();
SqlConnection myCon = DBcon.getInstance().conn();
string barcod = barcode;
string query = string.Format("SELECT * FROM Product WHERE Barcode = #barcode");
for (int tries = MaxRetries; tries >= 0; tries--) //<-- 'tries' at the end, are unreachable?.
{
try
{
myCon.Open();
SqlCommand com = new SqlCommand(query, myCon);
com.Parameters.AddWithValue("#barcode", barcode);
SqlDataReader dr = com.ExecuteReader();
if (dr.Read())
{
pro.Barcode = dr.GetString(0);
pro.Name = dr.GetString(1);
}
break;
}
catch (Exception ex)
{
if (tries == 0)
Console.WriteLine("Exception: "+ex);
throw;
}
}
myCon.Close();
return pro;
When running the code, the program stops at the "for(.....)", and the exception: The connection was not closed. The connection's current state is open... This problem was the reason why I'm trying to make this method! If anyone knows how to resovle this problem, please write. Thanks
You do
myCon.Open();
inside the for loop, but
myCon = DBcon.getInstance().conn();
outside of it. This way you try to open the same connection multiple times. If you want to protect against loss of DB connection you need to put both inside teh loop
You should move the call to myCon.Open outside the for statement or wrap myCon.Open() checking the connection state before re-opening the connection:
if (myCon.State != ConnectionState.Open)
{
myCon.Open();
}
Edited for new information
How about using Transactions to preserve data integrity, getting on-the-fly connections for multiple access and wrapping them in Using statements to ensure connections are closed? eg
Using (SqlConnection myCon = new SqlConnection('ConnectionString'))
{
myCon.Open();
var transaction = myCon.BeginTransaction();
try
{
// ... do some DB stuff - build your command with SqlCommand but use your transaction and your connection
var sqlCommand = new SqlCommand(CommandString, myCon, transaction);
sqlCommand.Parameters.Add(new Parameter()); // Build up your params
sqlCommand.ExecuteNonReader(); // Or whatever type of execution is best
transaction.Commit(); // Yayy!
}
catch (Exception ex)
{
transaction.RollBack(); // D'oh!
// ... Some logging
}
myCon.Close();
}
This way even if you forget to Close the connection, it will still be done implicitly when the connection gets to the end of its Using statement.
Have you tried adding
myCon.Close();
Into a Finally block. It looks like it is never being hit if you have an exception. I would highly recommend that you wrap the connection, command object etc in Using statements. This will ensure they are disposed of properly and the connection is closed.

Categories

Resources