Tranaction and connection pooling in asp.net - c#

I have used my database access code as below:
//gets the connection and create transaction
SqlTransaction transaction = SelectConnection();
try
{
dsRecordDataset = new DataSet();
SqlParameter[] param = new SqlParameter[1];
string[] taleNames = new string[1];
taleNames[0] = "RecordSet";
param[0] = new SqlParameter("#Mode", Mode);
SqlHelper.FillDataset(transaction, CommandType.StoredProcedure,
"spProject", dsRecordDataset, taleNames, param);
transaction.Commit();
return dsRecordDataset;
}
catch (Exception ex)
{
transaction.Rollback();
throw ex;
}
Problem which I have found is I have never closed the connection so that the connection pool can overflow and give an error to the user sometimes. I need to clarify the following
When does the connection pool reset according to default settings in asp.net?
Does committing transaction has anything to do with the connection?
I tried to use following code after try catch block
finally
{
if (transaction.Connection.State == ConnectionState.Open)
{
transaction.Connection.Close();
}
}
but then the connection is null and gives a error.
Is there any way to close the connection in above code?

when does the connection pool reset according to default settings in asp.net?
If MinPoolSize is either not specified in the connection string or is specified as zero, the connections in the pool will be closed after a period of inactivity. However, if the specified MinPoolSize is greater than zero, the connection pool is not destroyed until the AppDomain is unloaded and the process ends.
does committing transaction has anything to do with the connection?
No, committing a connection does not (should not) close the connection
is there any way to close the connection in above code?
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# so that they will be returned to the connection pool. Connections that are not explicitly closed might not be added or returned to the pool.

You got the answers, but for the question 3) you might find the using statement intresting in this case. However it means a code change, but it is a good way to keep the resource critical objects safe. (like your SqlConnection)
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = connection.CreateCommand();
command.CommandText = "mysp_GetValue";
command.CommandType = CommandType.StoredProcedure;
connection.Open();
object ret = command.ExecuteScalar();
}
It is just a very simple example, but this statement automaticly calls the Dispose method of an object which implements the IDisposable interface. (Like the SqlConnection)
If you are intrested in this, here you can find more details and explanations:
Your Friend the C# Using Statement

Related

What if i don't close database connection in disconnected mode

I am doing windows forms application with connection to SQL Server (disconnected mode). Every action I handle in my application needs the connection. So I don't know where to close the connection.
I am asking what if i don't close the connection. I know that there is no runtime error that appears. But is there any other error that could appear?
There is a risk that if you are using the same connection for each method, from a private field or GetConnection() method etc.; you could end up trying to read/write when the connection is still open.
This could then throw errors and you could end up in a whole heap of it, if using a live SQL database.
If you can, create a new instance of a connection in a using statement each time you want to access the DB.
Like this:
var connectionString = "YourConnectionStringToTheDB";
var queryString ="YourSQLQueryHere"; // FROM * IN tbl SELECT * etc...
using (SqlConnection connection = new SqlConnection(
connectionString))
{
using (SqlCommand command = new SqlCommand(queryString, connection))
{
command.Connection.Open();
command.ExecuteNonQuery();
}
}
This way it is closed and disposed of when the code runs outside of the using statement's scope.
Notice that the SqlCommand is also in a using statement, as it too can be disposed of.
This is cleaner code and marks the objects for disposal by the Garbage Collector. (Google is your friend) - BIG topic; a lot of stuff to read.
Here is a similar question which gives you some more detail: The C# using statement, SQL, and SqlConnection
EDIT
Better still, you could wrap your SQL code in a try { } catch { } block to handle any errors at runtime.

SQL Connection Open Exception

I am working on a project which, up until today, has been fine. However now when I run it and it goes through a few different Stored Procedure calls it is throwing an InvalidOperationException with the message The connection was not closed. The connection's current state is open.
I get that I could put in a check to see if the connection is already open, but this code hasn't changed (it is under Version Control and isn't modified) so I'm looking for other potential explanations.
Could there be some lock in SQL which isn't being released? Is there a process which I should look out for and kill?
I can't really post the code as there is a lot of it, and it is split up into smaller methods which makes it harder to pull out individual items. E.g:
public SqlConnection Connection
{
get
{
this._connection.Open();
return _connection;
}
}
public IDataReader RetrieveRecord(int Id)
{
//SP
SqlCommand cmd = this.Connection.CreateCommand();
cmd.CommandText = "SelectRecord";
cmd.CommandType = CommandType.StoredProcedure;
//Parameters
cmd.Parameters.Add(new SqlParameter("#tID", Id));
//instruct the data reader to close its connection when its Close method is called by passing the CommandBehavior.CloseConnection
return cmd.ExecuteReader(CommandBehavior.CloseConnection);
}
Nothing massively complex, I just don't understand why this connection is now throwing an exception.
The DAL is not stable enough:
You open a Connection that is not closed if something goes wrong in RetrieveRecord.
You should create a new connection inside RetrieveRecord and close it there in a finally block.
Opening a connection is cheap thanks to Connection Pooling.
Problem is with the line
this._connection.Open();
Because you are trying to open an already opened connection.
Try this to check before opening a connection:
if (this._connection.State == ConnectionState.Closed)
this._connection.Open();
Sorted. Two reboots cleared whatever was keeping the connection open.
When you are talking about killing process, I think you know c# well.
You should always use
using()
{
}
Like:
using(SqlConnection con=new SqlConnection("connectionString"))
{
// Do something with con
using(SqlCommand cmd=new SqlCommand("cmdText",con))
{
// Do something with cmd
}
}
You know that SqlCommand and SqlConnection implement IDisposable
So when you put those objects within using, the connection closing and clean up job is automatically done.
No need to close the connection manually in the code, since using will do the work for you.

Do I need to wrap a TransactionScope by try/catch?

The MSDN contains this code example:
// This function takes arguments for 2 connection strings and commands to create a transaction
// involving two SQL Servers. It returns a value > 0 if the transaction is committed, 0 if the
// transaction is rolled back. To test this code, you can connect to two different databases
// on the same server by altering the connection string, or to another 3rd party RDBMS by
// altering the code in the connection2 code block.
static public int CreateTransactionScope(
string connectString1, string connectString2,
string commandText1, string commandText2)
{
// Initialize the return value to zero and create a StringWriter to display results.
int returnValue = 0;
System.IO.StringWriter writer = new System.IO.StringWriter();
try
{
// Create the TransactionScope to execute the commands, guaranteeing
// that both commands can commit or roll back as a single unit of work.
using (TransactionScope scope = new TransactionScope())
{
using (SqlConnection connection1 = new SqlConnection(connectString1))
{
// Opening the connection automatically enlists it in the
// TransactionScope as a lightweight transaction.
connection1.Open();
// Create the SqlCommand object and execute the first command.
SqlCommand command1 = new SqlCommand(commandText1, connection1);
returnValue = command1.ExecuteNonQuery();
writer.WriteLine("Rows to be affected by command1: {0}", returnValue);
// If you get here, this means that command1 succeeded. By nesting
// the using block for connection2 inside that of connection1, you
// conserve server and network resources as connection2 is opened
// only when there is a chance that the transaction can commit.
using (SqlConnection connection2 = new SqlConnection(connectString2))
{
// The transaction is escalated to a full distributed
// transaction when connection2 is opened.
connection2.Open();
// Execute the second command in the second database.
returnValue = 0;
SqlCommand command2 = new SqlCommand(commandText2, connection2);
returnValue = command2.ExecuteNonQuery();
writer.WriteLine("Rows to be affected by command2: {0}", returnValue);
}
}
// The Complete method commits the transaction. If an exception has been thrown,
// Complete is not called and the transaction is rolled back.
scope.Complete();
}
}
catch (TransactionAbortedException ex)
{
writer.WriteLine("TransactionAbortedException Message: {0}", ex.Message);
}
catch (ApplicationException ex)
{
writer.WriteLine("ApplicationException Message: {0}", ex.Message);
}
// Display messages.
Console.WriteLine(writer.ToString());
return returnValue;
}
I'm unclear:
When do I need to catch TransactionAbortedException?
I'm currently storing a connection to the DB over app lifetime instead of opening and closing it each time. Does this conflict with using transactions? (Or is this a flaw in general?)
What do I need to do in case I don't care about whether the value was actually inserted? (I just want to make sure the DB does not get corrupted.)
No, TransactionScope doesn't need try/catch, because you should already be using it via using, and the last step (as per the example) should be to mark it completed. If it hits Dispose() without being completed, then it rolls back.
Re your bullets:
you don't, unless you have a very specific reason to handle that exception; I have never had to handle that scenario in a specific way - it is so unexpected that I'm happy for it to bubble up as a genuine exceptional event
storing your own open connection is not a great idea here - in addition to the potential threading issues, and having unnecessary open connections: you're ignoring the fact that there is already connection pooling built in by default (at least, with SQL Server). Meaning : you create/open a new SqlConnection as you need it (tightly scoped) and the pool worries about actual connections - you are potentially adding overhead here, but gaining very little (it is very quick to find an existing connection in the pool). If you check carefully, you'll probably notice that even when you Close() your connection, the db-server reports it in use; that is because your Close() merely put it back into the pool for re-use
nothing much; the transaction should be ACID
It is not a good practice to keep an open connection for ever.
If you are working on a webapplication, then you will easily reach to max connections.
Better keep the connection instance with you always and open the connnection Do what ever db operation and then close the connection.
Use Using (){}, is the right way to handle the DB component.

C# SQL Distributed transaction completed. Either enlist this session in a new transaction or the NULL transaction

I'm getting this error (Distributed transaction completed. Either enlist this session in a new transaction or the NULL transaction.) when trying to run a stored procedure from C# on a SQL Server 2005 database. I'm not actively/purposefully using transactions or anything, which is what makes this error weird. I can run the stored procedure from management studio and it works fine. Other stored procedures also work from C#, it just seems to be this one with issues. The error returns instantly, so it can't be a timeout issue. The code is along the lines of:
SqlCommand cmd = null;
try
{
// Make sure we are connected to the database
if (_DBManager.CheckConnection())
{
cmd = new SqlCommand();
lock (_DBManager.SqlConnection)
{
cmd.CommandText = "storedproc";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Connection = _DBManager.SqlConnection;
cmd.Parameters.AddWithValue("#param", value);
int affRows = cmd.ExecuteNonQuery();
...
}
}
else
{
...
}
}
catch (Exception ex)
{
...
}
It's really got me stumped. Thanks for any help
It sounds like there is a TransactionScope somewhere that is unhappy. The _DBManager.CheckConnection and _DBManager.SqlConnection sounds like you are keeping a SqlConnection hanging around, which I expect will contribute to this.
To be honest, in most common cases you are better off just using the inbuilt connection pooling, and using your connections locally - i.e.
using(var conn = new SqlConnection(...)) { // or a factory method
// use it here only
}
Here you get a clean SqlConnection, which will be mapped to an unmanaged connection via the pool, i.e. it doesn't create an actual connection each time (but will do a logical reset to clean it up).
This also allows much more flexible use from multiple threads. Using a static connection in a web app, for example, would be horrendous for blocking.
From the code it seems that you are utilizing an already opened connection. May be there's a transaction pending previously on the same connection.

.net SqlConnection not being closed even when within a using { }

Please help!
Background info
I have a WPF application which accesses a SQL Server 2005 database. The database is running locally on the machine the application is running on.
Everywhere I use the Linq DataContext I use a using { } statement, and pass in a result of a function which returns a SqlConnection object which has been opened and had an SqlCommand executed using it before returning to the DataContext constructor.. I.e.
// In the application code
using (DataContext db = new DataContext(GetConnection()))
{
... Code
}
where getConnection looks like this (I've stripped out the 'fluff' from the function to make it more readable, but there is no additional functionality that is missing).
// Function which gets an opened connection which is given back to the DataContext constructor
public static System.Data.SqlClient.SqlConnection GetConnection()
{
System.Data.SqlClient.SqlConnection Conn = new System.Data.SqlClient.SqlConnection(/* The connection string */);
if ( Conn != null )
{
try
{
Conn.Open();
}
catch (System.Data.SqlClient.SqlException SDSCSEx)
{
/* Error Handling */
}
using (System.Data.SqlClient.SqlCommand SetCmd = new System.Data.SqlClient.SqlCommand())
{
SetCmd.Connection = Conn;
SetCmd.CommandType = System.Data.CommandType.Text;
string CurrentUserID = System.String.Empty;
SetCmd.CommandText = "DECLARE #B VARBINARY(36); SET #B = CAST('" + CurrentUserID + "' AS VARBINARY(36)); SET CONTEXT_INFO #B";
try
{
SetCmd.ExecuteNonQuery();
}
catch (System.Exception)
{
/* Error Handling */
}
}
return Conn;
}
I do not think that the application being a WPF one has any bearing on the issue I am having.
The issue I am having
Despite the SqlConnection being disposed along with the DataContext in Sql Server Management studio I can still see loads of open connections with :
status : 'Sleeping'
command : 'AWAITING COMMAND'
last SQL Transact Command Batch : DECLARE #B VARBINARY(36); SET #B = CAST('GUID' AS VARBINARY(36)); SET CONTEXT_INFO #B
Eventually the connection pool gets used up and the application can't continue.
So I can only conclude that somehow running the SQLCommand to set the Context_Info is meaning that the connection doesn't get disposed of when the DataContext gets disposed.
Can anyone spot anything obvious that would be stopping the connections from being closed and disposed of when the DataContext they are used by are disposed?
From MSDN (DataContext Constructor (IDbConnection)):
If you provide an open connection, the
DataContext will not close it.
Therefore, do not instantiate a
DataContext with an open connection
unless you have a good reason to do
this.
So basically, it looks like your connections are waiting for GC to finalize them before they will be released. If you have lots of code that does this, one approach might be to overide Dispose() in the data-context's partial class, and close the connection - just be sure to document that the data-context assumes ownership of the connection!
protected override void Dispose(bool disposing)
{
if(disposing && this.Connection != null && this.Connection.State == ConnectionState.Open)
{
this.Connection.Close();
this.Connection.Dispose();
}
base.Dispose(disposing);
}
Personally, I would happily give it (regular data-context, w/o the hack above) an open connection as long as I was "using" the connection (allowing me to perform multiple operations) - i.e.
using(var conn = GetConnection())
{
// snip: some stuff involving conn
using(var ctx = new FooContext(conn))
{
// snip: some stuff involving ctx
}
// snip: some more stuff involving conn
}
The SqlProvider used by the LINQ DataContext only closes the SQL connection (through SqlConnectionManager.DisposeConnection) if it was the one to open it. If you give an already-open SqlConnection object to the DataContext constructor, it will not close it for you. Thus, you should write:
using (SqlConnection conn = GetConnection())
using (DataContext db = new DataContext(conn))
{
... Code
}
I experienced the same issue using the Entity Framework. My ObjectContext was wrapped around a using block.
A connection was established when I called SaveChanges(), but after the using statement was out of scope, I noticed that SQL Management Studio still had a "AWAITING COMMAND" for the .NET SQL Client.
It looks like this has to do with the behavior of the ADO.NET provider which has connection pooling turned on by default.
From "Using Connection Pooling with SQL Server" on MSDN (emphasis mine):
Connection pooling reduces the number of times that new connections need to be opened. The pooler maintains ownership of the physical connection. It manages connections by keeping alive a set of active connections for each given connection configuration. Whenever a user calls Open on a connection, the pooler looks to see if there is an available connection in the pool. If a pooled connection is available, it returns it to the caller instead of opening a new connection. When the application calls Close on the connection, the pooler returns it to the pooled set of active connections instead of actually closing it. Once the connection is returned to the pool, it is ready to be reused on the next Open call.
Also ClearAllPools and ClearPool seems useful to explicitly close all pooled connections if needed.
I think the connection, while no longer referenced, is waiting for the GC to dispose of it fully.
Solution:
Create your own DataContext class which derives from the auto-generated one. (rename the base one so you don't have to change any other code).
In your derived DataContext - add a Dispose() function. In that - dispose the inner connection.
Well thanks for the help chaps, it has been solved now..
Essentially I took elements of most of the answers above and implemented the DataContext constructor as above (I already had overloaded the constructors so it wasn't a big change).
// Variable for storing the connection passed to the constructor
private System.Data.SqlClient.SqlConnection _Connection;
public DataContext(System.Data.SqlClient.SqlConnection Connection) : base(Connection)
{
// Only set the reference if the connection is Valid and Open during construction
if (Connection != null)
{
if (Connection.State == System.Data.ConnectionState.Open)
{
_Connection = Connection;
}
}
}
protected override void Dispose(bool disposing)
{
// Only try closing the connection if it was opened during construction
if (_Connection!= null)
{
_Connection.Close();
_Connection.Dispose();
}
base.Dispose(disposing);
}
The reason for doing this rather than some of the suggestions above is that accessing this.Connection in the dispose method throws a ObjectDisposedException.
And the above works as well as I was hoping!
The Dispose should close the connections, as MSDN points out:
If the SqlConnection goes out of
scope, it won't be closed. Therefore,
you must explicitly close the
connection by calling Close or
Dispose. Close and Dispose are
functionally equivalent. If the
connection pooling value Pooling is
set to true or yes, the underlying
connection is returned back to the
connection pool. On the other hand, if
Pooling is set to false or no, the
underlying connection to the server is
closed.
My guess would be that your problem has something to do with GetContext().

Categories