Connection does not close like it should - c#

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
}

Related

Is it safe to rely on SqlConnection retry logic while using SqlCommand?

I was using Microsoft.Practice.TransientFaultHandling block for retry logic.
Now I switched my application to .Net 4.8 and use the new build in retry logic for SqlConnection.
I was wondering if I need a special retry logic for my SqlCommand (I used Polly before) or if this is also build in. There is no possibility to log a retry when relying on the build in functions which makes it really hard to test.
Microsoft states here :
"There is a subtlety. If a transient error occurs while your query is
being executed, your SqlConnection object doesn't retry the connect
operation. It certainly doesn't retry your query. However,
SqlConnection very quickly checks the connection before sending your
query for execution. If the quick check detects a connection problem,
SqlConnection retries the connect operation. If the retry succeeds,
your query is sent for execution."
I tested this by just disconnecting and reconnecting the internet within the retry time range and my command got executed after a while.
So it seems to work for this simple scenario. But is it really safe to rely on this or do I still have to implement a retry logic for my SqlCommand?
Here is my code:
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(ConnectionString);
builder.ConnectRetryCount = 5;
builder.ConnectRetryInterval = 3;
MyDataSet m_myDataSet = new MyDataSet();
using (SqlConnection sqlConnection = new SqlConnection(builder.ConnectionString))
{
try
{
sqlConnection.Open();
}
catch (SqlException sqlEx)
{
// do some logging
return false;
}
try
{
using (SqlCommand cmd = new SqlCommand(selectCmd, sqlConnection))
{
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(m_myDataSet, tableName);
}
}
}
}
The answer to your question is to analyze why your connection to the database is open so long that it is going idle and timing out. The ConnectRetryCount and ConnectRetryInterval properties allow you to adjust reconnection attempts after the server identifies an idle connection failure. I would follow the Microsoft recommendations on this one:
Connection Pooling Recommendation
We strongly recommend that you always close the connection when you
are finished using it so that the connection will be returned to the
pool. You can do this using either the Close or Dispose methods of the
Connection object, or by opening all connections inside a using
statement in C#, or a Using statement in Visual Basic. Connections
that are not explicitly closed might not be added or returned to the
pool. For more information, see using Statement or How to: Dispose of
a System Resource for Visual Basic.
Open your connections and close them when no longer needed like this:
MyDataSet m_myDataSet = new MyDataSet();
try
{
using (SqlConnection sqlConnection = new SqlConnection(ConnectionString))
{
sqlConnection.Open();
using (SqlCommand cmd = new SqlCommand(selectCmd, sqlConnection))
{
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(m_myDataSet, tableName);
}
}
}
}
catch (SqlException sqlEx)
{
// do some logging
return false;
}
Hope that helps.
Happy coding!!!

C# Using one SqlConnection for multiple queries

How to correctly use one SqlConnection object for multiple queries?
SqlConnection connection = new SqlConnection(connString);
static void SqlQuery(SqlConnection conn, string cmdString)
{
using (conn)
{
if (conn.State != ConnectionState.Open)
{
conn.Close();
conn.Open();
}
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = cmdString;
cmd.ExecuteNonQuery();
}
}
Function SqlQuery after 1st invoking throws System.InvalidOperationException "ConnectionString property not initialized"
In short don't do it
Creating a new instance of the class SqlConnection does not create a new network connection to SQL Server, but leases an existing connection (or creates a new one). .NET handles the physical connection pooling for you.
When you have finished with your connection (through which you can send multiple queries) just Close() or Dispose() (or use a using{} block preferably).
There is no need, and not good practise, to cache instances of the SqlConnection class.
Update
This is a better pattern for your method, you dont have to worry about the connections state
static void SqlQuery(string cmdString)
{
using (var connection = new SqlConnection(connString))
using (var cmd = connection.CreateCommand(cmdString, connection))
{
connection.Open();
// query
cmd.ExecuteNonQuery();
}
}
It depends on what you really mean/intend to do. If you mean batching a set of commands? Then yes,
it's arguably better to use one connection. Yes, connection pooling does save (all of) us, but if you really thought about it, what does it do? Yup, it reuses connections...
Performing Batch Operations
tips/pointers on SqlCommand as well
Hth.

Working on "using" statement in ADO.NET

I want to properly dispose the SqlConnection object whenever i come out of the method. So im using the "using" statement as shown below.
public int Hello()
{
using(SqlConnection con=new SqlConnection(constring))
{
using(SqlCommand cmd=new SqlCommand(Query,con))
{
try
{
con.Open();
return cmd.ExecuteNonQuery();
}
catch(Exception ex)
{
throw ex;
}
finally
{
con.Close()
}
}
}
}
Now, what i want to know is, Will the above code
Dispose the Connection properly when an Exception is occured in ExecuteNonQuery.
Make sure we will not get any ConnectionPool issues
Make sure the data is returned properly
If an exception occurs in SqlConnection will it dispose the object?
Can anyone help me on this?
You don't need the try/catch if you're just going to throw it, just change your code to this:
public int Hello()
{
using(SqlConnection con=new SqlConnection(constring))
{
using(SqlCommand cmd=new SqlCommand(Query,con))
{
con.Open();
return cmd.ExecuteNonQuery();
}
}
}
and regardless of what happens, exception or not, the connection will get closed if it's open and disposed.
Dispose the Connection properly when an Exception is occured in ExecuteNonQuery.
Yes
Make sure we will not get any ConnectionPool issues
i guess you mean connections would be properly relieved after executing query. if that is your question than You should not by using this approach.
Make sure the data is returned properly
using has nothing to do with returning data
If an exception occurs in SqlConnection will it dispose the object?
Yes
though you can rewrite your code as
using(SqlConnection con=new SqlConnection(constring))
{
using(SqlCommand cmd=new SqlCommand(Query,con))
{
try
{
con.Open();
return cmd.ExecuteNonQuery();
}
catch(Exception ex)
{
throw;
}
}
}
You should not use the using statement for sqlconnection.
using(SqlConnection con=new SqlConnection(constring))
Better you use try,catch and finally block to close the connection. So even if exception occurs in try & catch the finally block will execute and close the connection if its open.
The reason behind this is, think of below situaion.
Create object of a class that handles all database operation
e.g. DBUtility objDB = new DBUtility()
the above statement creates object of class and also initializes the sqlconnection variable from the constructor.
Now i am using the object objDB for executing multiple queries one by one. For this it should initialize the sqlconnection object only once and use it for its whole life (life obj objDB).
In your case the sqlconnection will be initialized as and when the method is called.
So simply init the connection once and open/close it for each of your operations. Your connection will automatically disposed by Garbage collector when objDB is disposed.

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

SQL server and .NET memory constraints, allocations, and garbage collection

I am running .NET 3.5 (C#) and SQL Server 2005 (for our clients). The code that we run does some regression math and is a little complicated. I get the following error when I run multiple pages on our site:
.NET Framework execution was aborted by escalation policy because of out of memory.
System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
System.InvalidOperationException:
I'm trying to figure out what is the root cause of this: is it a database issue or my C## code? or is it concurrency with locks when running queries? or somethin else?
The code is erroring here:
erver.ScriptTimeout = 300;
string returnCode = string.Empty;
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MainDll"].ToString())) {
connection.Open();
using (SqlCommand command = new SqlCommand(sql.ToString(), connection)) {
command.CommandType = CommandType.Text;
command.CommandTimeout = 300;
returnCode = (string)command.ExecuteScalar();
//Dispose();
}
//Dispose();
}
Our contractor wrote a bunch of code to help with SQL connections in an App_Code/sqlHelper.s file. Some of them are like this:
public static SqlDataReader GetDataReader(string sql, string connectionString, int connectionTime) {
lock (_lock) {
SqlConnection connection = null;
try {
connection = GetConnection(connectionString);
//connection.Open();
using (SqlCommand cmd = new SqlCommand(sql, connection)) {
cmd.CommandTimeout = connectionTime;
WriteDebugInfo("GetDataReader", sql);
return cmd.ExecuteReader(CommandBehavior.CloseConnection);
}
}
catch (Exception e) {
if (connection != null)
connection.Dispose();
throw new DataException(sql, connectionString, e);
}
}
}
Should there be some deallocation of memory somewhere?
The problem is that, for some reason, your DataReader isn't being closed. An exception? The method user didn't remember to close the DataReader?
A function that returns a DataReader to be used outside its body leaves the responsibility of closing it to outer code, so there's no guarantee that the Reader will be closed. If you don't close the reader, you cannot reuse the connection in which it was opened.
So returning a DataReader from a function is a very bad idea!
You can see a whole discussion on this subject here.
Look for the usages of this function (GetDataReader), and check if there's guarantee that the reader is getting closed. And, most importantly, that there is no possibility that this code re-enters and uses the same collection to open a new DataReader before the first is closed. (Don't be mislead by the CommandBehavior.CloseConnection. This only takes care of closing the connection when the DataReader is closed... only if you don't fail to close it)
This is because your data reader is already filled in. Its always a better way to release the data reader, command , data set , data table and close the connection in finally block.
Make use of Dispose() and Close() methods .

Categories

Resources