I have web application which contains the class to connect sql server. I have written the connection class like below
public SqlConnection DbConnectSql()
{
string str = System.Configuration.ConfigurationManager.ConnectionStrings["conStr"].ToString();
_con = new SqlConnection(str);
if (_con.State == ConnectionState.Open)
_con.Close();
_con.Open();
return _con;
}
When I am using the above code on the production server, some times the connection is not getting opened. The connection works fine after restarting the IIS. I have to do the IIS restart every two days. to work the sql connection. We didn’t get the exact exception of this issue.
To solve this, do we need to close the connection for all other cases except “_con.State == ConnectionState.Closed”? If we do so, is there any after affect for this code?
Modify
if (_con.State == ConnectionState.Open)
_con.Close();
_con.Open();
in
if (_con.State == ConnectionState.Closed)
_con.Open();
and try.
Usually it's not good practice to check if a connection is open when you start it then close it immediately and reopen it immediately as there could be latency issues.
It makes much more sense to check if there is any connection open with that session (connection == Connection.Closed) and then, if it's closed, open it, else do nothing because I am already connected.
This way, beyond being more logically meaningful is also more concise.
Also, in your code, when you use your SqlConnection, wrap them in a
using(_con)
{
//code here, sql stuff
};
statement, as it will manage itself all the closing and disposing connection stuff so you are sure when your sql logic is done everything gets disposed correctly without having to call Close and Dispose methods manually.
Let me know if it worked.
do we need to close the connection for all other cases
Sure, simply because all connections are created in a single Pool. See https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql-server-connection-pooling
Try to minimize connection creations (or reusing existing ones)
After finish usage of it, call con.Close() then con.Dispose() to insure you free resources
Related
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.
I am developing a .NET web application with C# and SQL Server as database, being newbie for both technologies. I have a problem when I attempt to save a lot of information at the same time.
My code is simple:
SqlConnection cn = null;
try
{
using (TransactionScope scope = new TransactionScope())
{
using (cn = Util.getConnection())
{
cn.Open();
BusinessObject.saveObject1(param1, cn);
BusinessObject.saveObject2(param2, cn);
BusinessObject.saveObject3(param3, cn);
BusinessObject.saveObject4(param4, cn);
...
scope.Complete();
}
}
I always use the same connection object because if an error happens, I must revoke any change in my data and the same behaviour if the process is ok, is needed.
I don't mind it the process of saving takes a lot of time, in my application is perfectly normal because I have to save a lot of information.
The weirdness here is:
When I execute this function in the same local area network of the database, it perfectly works.
However, if I execute it from outside, such as, connected by a VPN and consequently with higher latency, I get an error with the message: "The transaction associated with the current connection has completed but has not been disposed. The transaction must be disposed before the connection can be used to execute SQL statements."
I have tried to change the timeout of the database through the connection string in the web.config but it didn't resolve anything. Also, if after each executeNonQuery() statement I do a cn.Dispose(), I get an error in the next attempt to use the connection object.
Do I have to change the parameters of TransactionScope object? Is there another better way to do this?
Thanks in advanced.
This is due to a timeout error. The TransactionScope might decide to rollback the transaction in case of a timeout.
You need to increase the timeout value in the TransactionScope constructor. The default max. timeout is 10min.
Move scope.Complete(); outside the connection block (MSDN article).
Did you try setting the Timeout = 0 in your Util.getConnection() function ? A value of 0 indicates no limit. This will complete the job surely. By setting the Timeout = 0 will complete every long operation job.
I'm making a web application in C# with ASP.Net, and I'm using an SQL database for it. In the guides I saw (about SqlConnection and SqlCommand) they open and close the SQL connection each time they want to send a query. But I'm not sure this is the best way to handle the connection, because I also learned some PHP, and as far as I know in PHP you open a connection only once, at start. So what is the best way to handle the connection?
You should generally have one connection, and transaction, for the length of the web request.
If you have two connections, you could potentially have inconsistent data. e.g. in the first query you check the bank balance, then you close it. You then add $5 to the balance and save that away in the next connection. What if someone else added $5 between the two connections? It would go missing.
The easiest thing to do is to open the connection global.asax BeginRequest and save that away into the HttpContext. Whenever you need a connection, pull it from there. Make sure that you .Close the connection in your EndRequest
Also, read up here on connection pooling: http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx
It is not 'expensive' to repeatedly open and close connections, provided the username is the same each time.
Ado.Net has connection pooling already managed for you, so you don't need to worry about reusing connections.
You could use the Using statement to close and dispose connection:
DataTable dt = new DataTable();
using (SqlConnection conn = new SqlConnection("my_connection_string"))
{
using (SqlDataAdapter adapter = new SqlDataAdapter("SELECT * from Table", conn))
{
conn.open();
adapter.Fill(dt);
}
}
Normal practice in .NET is to open a SqlConnection and use a SqlCommand, then dispose of both of them.
using(SqlConnection connection = new SqlConnection("myConnectionString"))
{
using(SqlCommand command = new SqlCommand("dbo.SomeProc"))
{
// Execute the command, when the code leaves the using block, each is disposed
}
}
As a connection to database is an expensive resource it's better to open sql connection as late as possible and close early. So you should open the connection just before executing a command and close it once you have executed it.
On the other hand if you are going to execute many commands in a short interval of time it's better to open the connection once and close after all the commands are executed.
For starters they do not as there is a connection pool that is being used, but SqlCommand has an overload to take a connection object, so you could keep the connection around and pass it.
Generally:
using (var ts = new TransactionScope())
{
using (var connection = new SqlConnection(...))
{
using (var command = new SqlCommand(connection, ...)
{
...
}
using (var command = new SqlCommand(connection, ...)
{
...
}
}
ts.Complete();
}
Of course I would recommend using LINQ-to-SQL or EF at this point.
Try Data Access Application Block in the Enterprise Library if you do not want to worry about opening and closing the connections.
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.
I've read that in PHP non-persistent open links are automatically closed at the end of the script's execution. So what's up with asp.net?
Simple: PHP and ASP.NET aren't the same thing. They have different "rules". Don't try to write code in one environment as if it were the other.
In .NET should almost always open a connection as late as you can and close it as early as you can, letting the built-in connection pool handle the "real" connection to the database. Don't leave it to the GC/finalizer to tidy up connections for you.
Yes you need to close open connections to database. ADO.NET has a connection pool, and open connections are reserved to you while it stays opened. When you close it, it will be available to other connection requests.
But if you're using DataAdapter, and you don't open connection manually, you don't need to close it. DataAdapter manages it and closes it's own connection :
SqlConnection nwindConn = new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind");
SqlCommand selectCMD = new SqlCommand("SELECT CustomerID, CompanyName FROM Customers", nwindConn);
selectCMD.CommandTimeout = 30;
SqlDataAdapter custDA = new SqlDataAdapter();
custDA.SelectCommand = selectCMD;
DataSet custDS = new DataSet();
custDA.Fill(custDS, "Customers");
The easiest way to do this is with a using block:
var cmd = new MySqlCommand("command text here");
using (var con = new MySqlConnection("connection string")) {
cmd.Connection = con;
cmd.Connection.Open();
//execute command here
}
The connection object will be automatically disposed when you leave the scope.
Well, its a good practice to release unmanaged data manually, although the finalizer would take care of it eventually.
ASP.Net is said to be "managed", but that really only refers to memory.
When your page instance goes out of scope your are guaranteed that the memory object which wraps the connection will eventually be collected and cause it to be closed, but you are not guaranteed when that will happen. Since it's much more efficient to release memory in larger batches, your connection may hang around a while, and if you get a lot of these that can cause a big problem.
So, you should make sure your connection is closed.
Since most of the connection objects implement IDisposable and have finalizers you could technically rely on the garbage collector to close the connection for you since the finalizer will call Close() on the connection. Obviously this is a bad idea - wrap your connection objects in using statements or explicitly close them when you are done with them.
Since I require 50 reputation to comment on someones post, I am posting my comment to Adam Lassek as an answer. His approcah is the corrct way to go. The Using satement will clean up the unmanaged code.