ADO.NET Funny Connection Pool Behaviour when bury SQL Exception - c#

I am catching a sql exception and not rethrowing it. This seems to mean that the connection is not returned to the pool as I would expect. Is this possible?
using (IDbCommand paymentCommand = this.Connection.CreateCommand())
{
try
{
//database stuff
}
catch (SqlException ex)
{
//LOG CALL
}
}

why don't you put using(...){} inside try{} block? This way even if exception is thrown, using block will dispose off IDBcmd obj.

It's not clear in your question how you are creating the connection, but you do need to make sure you Open it, then Close it, regardless of errors or not.
Typically I'll do something like this:
SqlConnection connection = null;
try {
connection.Open();
// Do stuff like run a query, setup your IDbCommand, etc.
} catch (Exception ex) {
// Log error
} finally {
if (connection != null) {
connection.Close();
}
}
This way, no matter what happens, your connection will be closed and returned to the pool. If you fail to Close(), you'll "leak" that connection and eventually run out of pooled connections to draw from. The lifetime of the connection should generally only be as long as it takes to issue your sql command, at which point you should be closing it.

It's not clear what you are experiencing with the connection pool. However, I would definitely wrap your connection in a using statement.
This is what I usually use (note that dac.GetConnection() is simply a class that centralizes the code to get a connection object):
using (SqlConnection connection = dac.GetConnection())
{
using (SqlCommand command = new SqlCommand("myProc", connection))
{
command.CommandType = CommandType.StoredProcedure;
try
{
connection.Open();
//add params, run query
}
catch (Exception ex)
{
//handle/log errror
}
finally
{
if (connection.State == ConnectionState.Open)
connection.Close();
}
}
}

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

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.

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.

Does using (var connection = new SqlConnection("ConnectionString")) still close/dispose the connection on error?

I have the following code
try
{
using (var connection = new SqlConnection(Utils.ConnectionString))
{
connection.Open();
using (var cmd = new SqlCommand("StoredProcedure", connection))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
var sqlParam = new SqlParameter("id_document", idDocument);
cmd.Parameters.Add(sqlParam);
int result = cmd.ExecuteNonQuery();
if (result != -1)
return "something";
//do something here
return "something else";
}
}
//do something
}
catch (SqlException ex)
{
return "something AKA didn't work";
}
The question is: Does var connection still get closed if an unexpected error happens between the using brackets ({ })?
The problem is that most of my calls to stored procedures are made this way, and recently I have been getting this error:
System.InvalidOperationException: Timeout expired. The timeout
period elapsed prior to obtaining a connection from the pool. This
may have occurred because all pooled connections were in use and max
pool size was reached.
The other way I access the DB is through nHibernate.
using Statement (C# Reference)
The using statement ensures that Dispose is called even if an
exception occurs while you are calling methods on the object. You can
achieve the same result by putting the object inside a try block and
then calling Dispose in a finally block; in fact, this is how the
using statement is translated by the compiler. The code example
earlier expands to the following code at compile time (note the extra
curly braces to create the limited scope for the object):
Yes, if it gets into the body of the using statement, it will be disposed at the end... whether you reached the end of the block normally, exited via a return statement, or an exception was thrown. Basically the using statement is equivalent to a try/finally block.
Is that the only place you acquire a connection? Has your stored procedure deadlocked somewhere, perhaps, leaving lots of connections genuinely "busy" as far as the client code is concerned?
In terms of your connection pool running out of available connections, if you are in a distributed environment and using many applications to access SQL Server but they all use the same connection string, then they will all be using the same pool on the server. To get around this you can change the connection string for each application by setting the connection WorkstationID to the Environment.MachineName. This will make the server see each connection as different and provide a pool to each machine instead of sharing the pool.
In the below example we even pass in a token to allow an application on the same machine to have multiple pools.
Example:
private string GetConnectionStringWithWorkStationId(string connectionString, string connectionPoolToken)
{
if (string.IsNullOrEmpty(machineName)) machineName = Environment.MachineName;
SqlConnectionStringBuilder cnbdlr;
try
{
cnbdlr = new SqlConnectionStringBuilder(connectionString);
}
catch
{
throw new ArgumentException("connection string was an invalid format");
}
cnbdlr.WorkstationID = machineName + connectionPoolToken;
return cnbdlr.ConnectionString;
}
Replace your above code.. by this.. and check again..
try
{
using (var connection = new SqlConnection(Utils.ConnectionString))
{
connection.Open();
using (var cmd = new SqlCommand("StoredProcedure", connection))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
var sqlParam = new SqlParameter("id_document", idDocument);
cmd.Parameters.Add(sqlParam);
int result = cmd.ExecuteNonQuery();
if (result != -1)
return "something";
//do something here
return "something else";
}
connection.Close();
connection.Dispose();
}
//do something
}
catch (SqlException ex)
{
return "something AKA didn't work";
}
Here's a reference:
http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx
What I know is that if you use an object within the using {} clause, that object inherits the IDisposable interface (i.e. SqlConnection inherits DbConnection, and DbConnection inherits IDisposable), which means if you get an exception, any object will be closed and disposed properly.

If I catch exceptions inside a using statement for a SqlConnection, does the using still handle closing and disposing my connection?

I'm going through some old C#.NET code in an ASP.NET application making sure that all SqlConnections are wrapped in using blocks.
This piece of code used to open cn and da and close and dispose them in both the catch block and the end of the method. I added the usings and can't figure out for certain if the using blocks still handle disposing of the connection if an exception is thrown in the try and caught in the catch. This question seems to suggest that it does.
using (SqlConnection cn = new SqlConnection(Global.sDSN))
{
using (SqlDataAdapter da = new SqlDataAdapter())
{
// do some stuff
try
{
// do stuff that might throw exceptions
}
catch (catch (System.Exception e)
{
//return something here
// can I ditch these because the using's handle it?
da.Dispose();
cn.Close();
cn.Dispose();
return msg;
}
}
}
Yes, they will. They're basically turned into a finally block.
So something like this:
using (SqlConnection cn = new SqlConnection(Global.sDSN))
{
....
}
is really turned into:
SqlConnection cn = new SqlConnection(Global.sDSN)
try
{
....
}
finally
{
cn.Dispose();
}
more or less - and the finally block is always executed, no matter what might have happened before in the try {.....} block.
When you use a using clause this is what's happening:
myobject = new object();
try{
// do something with myobject
}finally{
myobject.Dispose();
}
Hope this helps,
Best regards,
Tom.

Categories

Resources