In using Enterprise Library, there was an issue with having to manually close db connections, as GC, when scanning the heap, looks for items out of scope.
A connection that is part of a pool that is being used but the connection state is broken or fetching, but you have already received your results, will be kept open, and connection handles in the pool will run out.
Thus, adding manual connection checking and forcedly closing the connections is good form.
Now, take SubSonic. With an EntLib base, I am doing the following in a finally block:
public static bool GetISOCountryCodes(out DataSet dsISOCountryCodes, out Response dbResponse)
{
dbResponse = new Response();
dsISOCountryCodes = new DataSet();
StoredProcedure sp = null;
try
{
sp = SPs.GetISOCountryCodes(null);
dsISOCountryCodes = sp.GetDataSet();
// set the response object properties
dbResponse = new Response((int)sp.OutputValues[0]);
return dbResponse.IsValid;
}
catch (System.Exception ex)
{
return dbResponse.IsValid;
}
finally
{
if (sp.Command != null && sp.Command.ToDbCommand().Connection != null &&
sp.Command.ToDbCommand().Connection.State == ConnectionState.Open)
sp.Command.ToDbCommand().Connection.Close();
}
}
I know it's been said that you don't have to manually do this, as SubSonic will do this for you, however, I'd like to know if anyone has run into issues with SubSonic not closing connections (once again, as it uses EntLib at the root), and if there are better ways of accomplishing this.
Obviously, in all my data caller methods, I will reference one, say, "ConnectionCloser()" method.
Thanks.
This post was more of a notification for discussion. However, I'm not sure if the issue has actually been resolved with v5. So essentially the answer is to continue checking in the finally block.
Related
We are using Dapper for some data access activity and are using the standard recommended approach for connecting to database as follows:
public static Func<DbConnection> ConnectionFactory = () => new SqlConnection(ConnectionString);
However, if we try and execute a statement, in the docs it show that you need to first state:
using (var conn = ConnectionFactory())
{
conn.Open();
var result = await conn.ExecuteAsync(sql, p, commandType: CommandType.StoredProcedure);
return result;
}
That means, you have to explicitly open the connection. However, if we leave out the statement conn.open(), it also works and we are worried if in such cases the connection may not be disposed of properly.
I would appreciate any comments as to how the SQL gets executed without explicitly opening any connection.
Dapper provide two ways to handle connection.
First is - Allow Dapper to handle it.
Here, you do not need to open the connection before sending it to Dapper. If input connection is not in Open state, Dapper will open it - Dapper will do the actions - Dapper will close the connection.
This will just close the connection. Open/Close is different than Dispose. So, if you really want to Dispose the connection better switch to second way.
Second is - Handle all yourself.
Here, you should explicitly create, open, close and dispose the connection yourself.
Please refer to following links for more details:
https://stackoverflow.com/a/51138718/5779732
https://stackoverflow.com/a/41054369/5779732
https://stackoverflow.com/a/40827671/5779732
Looking at the source code for Dappers QueryAsync method
SqlMapper.Async.cs
private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn, Type effectiveType, CommandDefinition command)
{
using (var cmd = command.TrySetupAsyncCommand(cnn, info.ParamReader))
{
DbDataReader reader = null;
try
{
if (wasClosed) await cnn.TryOpenAsync(cancel).ConfigureAwait(false);
var func = tuple.Func;
if (command.Buffered)
{
var buffer = new List<T>();
var convertToType = Nullable.GetUnderlyingType(effectiveType) ?? effectiveType;
while (await reader.ReadAsync(cancel).ConfigureAwait(false))
{
object val = func(reader);
if (val == null || val is T)
{
buffer.Add((T)val);
}
else
{
buffer.Add((T)Convert.ChangeType(val, convertToType, CultureInfo.InvariantCulture));
}
}
while (await reader.NextResultAsync(cancel).ConfigureAwait(false)) { /* ignore subsequent result sets */ }
command.OnCompleted();
return buffer;
}
else
{
// can't use ReadAsync / cancellation; but this will have to do
wasClosed = false; // don't close if handing back an open reader; rely on the command-behavior
var deferred = ExecuteReaderSync<T>(reader, func, command.Parameters);
reader = null; // to prevent it being disposed before the caller gets to see it
return deferred;
}
}
finally
{
using (reader) { /* dispose if non-null */ }
if (wasClosed) cnn.Close();
}
}
}
Note this line (413):
using (var cmd = command.TrySetupAsyncCommand(cnn, info.ParamReader))
My question is, will my connection be disposed of correctly without me having to wrap my code calling in to this in a using block?
Note following line in the code you post:
private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn,....
That shows QueryAsync is an extension method of IDbConnection. That means, instance of connection is created in your code somewhere.
As mentioned here, there are two ways to manage connection with Dapper:
Fully manage yourself:
Here, you are fully responsible for opening and closing connection. This is just like how you treat connection while working with ADO.NET.
Allow Dapper to manage it:
Dapper automatically opens the connection (if it was not opened) and closes it (if it was opened by Dapper) for you.
Considering this, only choice remain here is to open/close connection in your code or allow Dapper to do this for you. If you are doing this yourself then Dapper does not interfere at all.
If you want to allow Dapper to handle the open/close connection for you and are worried that whether it will close it properly, then yes, it closes it properly.
Find following code in your post:
if (wasClosed) await cnn.TryOpenAsync(cancel).ConfigureAwait(false);
....
if (wasClosed) cnn.Close();
Dapper maintains the state/flag in wasClosed variable if connection was opened by Dapper. You can see in your code that the connection is also properly closed at the end. Further, you can further check the Dapper source code to see how the this is handled in multiple methods. Specially check SqlMapper.Async.cs and SqlMapper.cs files.
Now, this is all about open/close. What about Dispose? Following is what Marc Gravell says in one of the comment for this answer: https://stackoverflow.com/a/12629170/5779732
well, technically open/closed is different to disposed. If you are only going to be opening/closing around the individual calls, you might as well let dapper do it. If you are opening/closing at a wider granularity (per request, for example), it would be better for your code to do it and pass an open connection to dapper.
So, if you really want to Dispose the connection instead of just open/close, better you wrap it in using block in your code and pass open connection to Dapper. As mentioned in the comment, this post discusses difference between Dispose and Close.
I am using C# linq to sql application and my application is running 24*7 in servers. Now i am facing the issue database connections they are not closing so active connects reach to 200 and more. I used using syntax everywhere I am dealing the database directly.
But this is not solving my problem. Please check and let me know what best i can do for this.
Provider always disabled my database.
using (DataClassesDataContext DbContext = new DataClassesDataContext())
{
return DbContext.tblApiLinks.FirstOrDefault(U => U.ProviderName == ProviderName);
}
using (DataClassesDataContext DbContext = new DataClassesDataContext())
{
tblApiLink Apilink = new tblApiLink();
Apilink.ApiUrl = Url;
Apilink.ApiKey = Key;
Apilink.ProviderName = Provider;
DbContext.tblApiLinks.InsertOnSubmit(Apilink);
DbContext.SubmitChanges();
}
New Edits
Case 1. Please check these code it returning a table. Does this effect to close the connection?
public tblApiLink getData()
{
using (DataClassesDataContext DbContext = new DataClassesDataContext())
{
return DbContext.tblApiLinks.FirstOrDefault(U => U.ProviderName == ProviderName);
}
}
tblApiLink api = getData();
Case 2. If I used like this tblApiLinks lst= dbContext.tblApiLinks;
I think this will not close the connection and they will be active all time.
Case 3. Is there any way to close all sleeping connection which is active from long time and not in use.
In your "case 1" try to set a variable that stores what you want to return, and return the value after the using block is closed.
Example:
tblApiLink returnData = null;
using(DataClassesDataContext DbContext = new DataClassesDataContext())
{
returnData = DbContext.tblApiLinks.FirstOrDefault(U => U.ProviderName == ProviderName);
}
return returnData;
Side note: The type tblApiLink isn't correctly named according to convention, I suggest you refactor it if possible.
Case 2: I don't understand what you mean.
Case 3: You could use a singleton that handles connections and closes them, but the proper way to do this is disposing the connections that are no longer active. If you really want to kill active connections your best bet would be on the server, either manually or storing a procedure that you can call later on.
I'm writing an ASP.NET application. In my datalayer an sql connection is being opened and closed before and after querying. The SqlConnection is being kept as a private field of a single class. Every database call in the class uses the same structure:
conn.Open();
try
{
// database querying here
}
finally
{
conn.Close();
}
Yet, on very rare occasions I get the exception 'The connection was not closed. The connection's current state is open'. It's not possible to reproduce the problem since it originates very rarely from different parts of the code. There is some threading involved in my application but new threads also make new data layer classes and thus new connection objects.
I do not understand how it's possible to have a connection lingering around open using the code above. Shouldn't the connection always be closed after opening, making it impossible for the above exception to occur?
It's likely that an exception is being thrown in the try block that you aren't handling. See this note in MSDN for try-finally:
Within a handled exception, the associated finally block is guaranteed to be run. However, if the exception is unhandled, execution of the finally block is dependent on how the exception unwind operation is triggered.
I would recommend wrapping the connection in a using block anyway:
using (SqlConnection connection = new SqlConnection(connectionString))
{
//etc...
}
Alternatively, add a catch block to the try-finally:
conn.Open();
try
{
}
catch
{
}
finally
{
conn.Close();
}
you should close connections as soon as you operations finished. Try to open connections for the shortest time possible.
However it is best to use using it will call Dispose method even in case of exceptions.
using (SqlConnection conn= new SqlConnection(conStr))
{
//etc...
}
OR
1) Open the connection
2) Access the database
3) Close the connection
//conn.Open();
try
{
conn.Open();
//Your Code
}
finally
{
conn.Close();
conn.Dispose();//Do not call this if you want to reuse the connection
}
Sorry, If u filling bored. I have searched on several search engines but could not got any result. Anyway I am working in an App which database is mysql. Now I have created a database wrapper class and want to check if the connection is already opened. Could u help me?
String^ constring = L"datasource=localhost;port=3306;username=root;password=pass;database=eps;";
String^ my_query = L"select id from eps_users where usr = '" + this->user_name->Text + "' and psw = md5('" + this->pass_word->Text + "');";
MySqlConnection^ conDatabase = gcnew MySqlConnection(constring);
MySqlCommand^ cmd = gcnew MySqlCommand(my_query, conDatabase);
MySqlDataReader^ myreader;
try
{
conDatabase->Open();
myreader = cmd->ExecuteReader();
int count = 0;
while (myreader->Read())
{
count = count + 1;
}
if (count == 1){
MessageBox::Show("Username And Password is correct.", "Success", MessageBoxButtons::OK,
MessageBoxIcon::Information);
this->Hide();
Form2^ f2 = gcnew Form2(constring);
f2->ShowDialog();
}
else{
MessageBox::Show("Username And Password is not correct.", "Error", MessageBoxButtons::OK,
MessageBoxIcon::Error);
// <del>
this->Hide();
Form2^ f2 = gcnew Form2(constring);
f2->ShowDialog();
// </del>
}
}
catch (Exception^ ex)
{
MessageBox::Show(ex->Message);
}
conDatabase->Close();
I need to check if( conDatabase->HasBeenOpened()) { conDatabase->Open();}
The MySqlConnection type implements a feature called connection pooling that relies on the garbage collector to help recycle connections to your database, such that the best practice with regards to connection objects is to create a brand new object for most calls to the database, so that the garbage collector can correctly recycle the old ones. The process goes like this:
Create a new connection
Open the connection
Use the connection for one query/transaction
Dispose the connection
Where all four steps live within a single try/catch/finally block. (Also, the dispose step needs to happen inside the finally block!) Because you generally start with a brand new connection object, there's not typically a need to check if it's open first: you know it's closed. You also don't need to check the state after calling Open(): the method will block until it's finished, and throw an exception if it fails.
However, if you really are in one of the (rare!) situations where it's a good idea to preserve the connection for an extended period, you can check the state like this:
if( conDatabase->State == ConnectionState::Open)
Now, there is one other issue in that code I'd like to talk about. The issue comes down to this: what do you think will happen if I put the following into your username text box:
';DROP Table eps_users;--
If you think that it will try to execute that DROP statement in your database, you're right: it will! More subtle and damaging queries are possible, as well. This is a huge issue: there are bots that run full time crawling web sites looking for ways to abuse this, and even an corporate internal desktop apps will get caught from time to time. To fix this, you need to use Parameterized Queries for every instance where include user-provided data as part of your sql statement.
A quick example might look like this:
String^ my_query = L"select id from eps_users where usr = #userID;";
MySqlCommand^ cmd = gcnew MySqlCommand(my_query, conDatabase);
cmd->Parameters->AddWithValue(L"#userID", this->user_name->Text);