I tried this code on an array of 3 connection strings without any complaints.My question is, is it okay to invoke multiple dispose calls on the same object?
foreach (var s in strings)
{
connection.ConnectionString = s;
connection.Open();
connection.Close();
connection.Dispose();
}
Here is one way to do it:
bool TestConnection<T>(string connectionString) where T : IDbConnection, new
{
using(T con = new T())
{
con.ConnectionString = connectionString;
connection.Open();
return true;
}
}
Another way to implement connection testing code is with an extension method (note this does not dispose the connection object):
public static Tuple<bool, Exception> TestConnection(this IDbConnection connection)
{
try
{
connection.Open();
connection.Close();
return new Tuple<bool, Exception>(true, null);
}
catch(Exception e)
{
return new Tuple<bool, Exception>(false, e);
}
}
Please note in this version I'm returning a Tuple of bool and Exception so whoever use this code can get the information on why the connection failed, but not have to wrap the call in a try...catch block. Of course, you can choose to simply return a bool just like in the first example, this is just for demonstration purposes.
You should fix your code this way:
foreach (var s in strings)
{
connection.ConnectionString = s;
connection.Open();
connection.Close();
}
Connection doesn't need to dispose, or atleast you shoudln't dispose an object that you want to use again.
Anyway this isn't a good approach.
You should have a
using(DbContext db = new DbContext()){
//SQL Actions
}
for every db relative code, to avoid problems ^^
public bool TestConnection(IDbConnection con)
{
using (con)
{
try
{
con.Open();
con.Close();
return true;
}
catch
{
return false;
}
}
}
It's "ok" with what you are doing (completely different connect everytime with no ran queries) but as Amy said in the comments, it really doesn't get you anything special. Should probably abide by the wisdom of not reusing disposed objects.
Also for SqlConnection, calling Close then dispose is repetitive since it will call its close upon dispose.
Going to throw my code into the mix as well, comments in code:
private bool DBValidCheck(string connection)
{
//Using statement releases the object that implement iDisposable once it exits the block. Takes care of the dispose
using (var connection = new SqlConnection(connection))
{
try
{
connection.Open();
return true;
}
catch
{
return false;
}
}
}
Related
I have some instances where sometimes I want to execute code within the same connection (for using temp tables, etc), but most of the time I want to open and close the connection as soon as possible.
public int BulkInsert<T>(IDataReader dataReader, Dictionary<string, string> columnMappings = null, int timeoutInSeconds = 120)
{
if (_sqlConnection != null)
{
return BulkInsert<T>(dataReader, _sqlConnection, columnMappings, timeoutInSeconds);
}
using (var tempConnection = new SqlConnection(_connectionString))
{
return BulkInsert<T>(dataReader, tempConnection, columnMappings, timeoutInSeconds);
}
}
How can I make this code more clean and not two separate calls?
My attempt:
public int BulkInsert<T>(IDataReader dataReader, Dictionary<string, string> columnMappings = null, int timeoutInSeconds = 120)
{
var rv = 0;
var conn = _sqlConnection ?? new SqlConnection(_connectionString);
try {
rv = BulkInsert<T>(dataReader, conn, columnMappings, timeoutInSeconds);
} finally {
if (conn != _sqlConnection)
{
conn.Dispose();
}
}
return rv;
}
but I am not really happy with it.
P.S. I wasnt sure if this belonged to stackoverflow or programming but I figured because the use of using that it was pretty c# specific and more of a refactor than just an opinion of style
I'd recommend the following pattern
private void myFunc()
{
// The ensureConnection method does the null check and creates a connection
bool connectionEstablished;
SqlConnection connection = ensureConnection(out connectionEstablished);
try
{
// Do some work with the connection.
}
finally
{
// If the connection was established for this call only, the disposeConnection
// function carries out disposal (or caching etc).
disposeConnection(connection, connectionEstablished);
}
}
Its clear what you are trying to achieve and there is no branching. You could encapsulated the SqlConnection and the bool into a simple struct for convenience to cut out the OUT parameter.
The nice option here is that the function doens't know or care where its connection came from, whether it was cached or persisted from another call, and allows for easy multi-threading (the ensureConnection can lease out a persistent connection or create a new one as required if the persistent connection is already in use).
Oh I found this method based on C# conditional using block statement
private SqlConnection CreateTempConnectionIfNeeded()
{
return _sqlConnection == null ? new SqlConnection(_connectionString) : null;
}
public int BulkInsert<T>(IDataReader dataReader, Dictionary<string, string> columnMappings = null, int timeoutInSeconds = 120)
{
using (var tempConnection = CreateTempConnectionIfNeeded())
{
return BulkInsert<T>(dataReader, tempConnection ?? _sqlConnection, columnMappings, timeoutInSeconds);
}
}
Which is the proper way of using BeginTransaction() with IDbConnection in Dapper ?
I have created a method in which i have to use BeginTransaction(). Here is the code.
using (IDbConnection cn = DBConnection)
{
var oTransaction = cn.BeginTransaction();
try
{
// SAVE BASIC CONSULT DETAIL
var oPara = new DynamicParameters();
oPara.Add("#PatientID", iPatientID, dbType: DbType.Int32);
..........blah......blah............
}
catch (Exception ex)
{
oTransaction.Rollback();
return new SaveResponse { Success = false, ResponseString = ex.Message };
}
}
When i executed above method - i got an exception -
Invalid operation. The connection is closed.
This is because you can't begin a transaction before the connection is opened. So when i add this line: cn.Open();, the error gets resolved. But i have read somewhere that manually opening the connection is bad practice!! Dapper opens a connection only when it needs to.
In Entity framework you can handle a transaction using a TransactionScope.
So my question is what is a good practice to handle transaction without adding the line cn.Open()... in Dapper ? I guess there should be some proper way for this.
Manually opening a connection is not "bad practice"; dapper works with open or closed connections as a convenience, nothing more. A common gotcha is people having connections that are left open, unused, for too long without ever releasing them to the pool - however, this isn't a problem in most cases, and you can certainly do:
using(var cn = CreateConnection()) {
cn.Open();
using(var tran = cn.BeginTransaction()) {
try {
// multiple operations involving cn and tran here
tran.Commit();
} catch {
tran.Rollback();
throw;
}
}
}
Note that dapper has an optional parameter to pass in the transaction, for example:
cn.Execute(sql, args, transaction: tran);
I am actually tempted to make extension methods on IDbTransaction that work similarly, since a transaction always exposes .Connection; this would allow:
tran.Execute(sql, args);
But this does not exist today.
TransactionScope is another option, but has different semantics: this could involve the LTM or DTC, depending on ... well, luck, mainly. It is also tempting to create a wrapper around IDbTransaction that doesn't need the try/catch - more like how TransactionScope works; something like (this also does not exist):
using(var cn = CreateConnection())
using(var tran = cn.SimpleTransaction())
{
tran.Execute(...);
tran.Execute(...);
tran.Complete();
}
You should not call
cn.Close();
because the using block will try to close too.
For the transaction part, yes you can use TransactionScope as well, since it is not an Entity Framework related technique.
Have a look at this SO answer: https://stackoverflow.com/a/6874617/566608
It explain how to enlist your connection in the transaction scope.
The important aspect is: connection are automatically enlisted in the transaction IIF you open the connection inside the scope.
Take a look at Tim Schreiber solution which is simple yet powerful and implemented using repository pattern and has Dapper Transactions in mind.
The Commit() in the code below shows it.
public class UnitOfWork : IUnitOfWork
{
private IDbConnection _connection;
private IDbTransaction _transaction;
private IBreedRepository _breedRepository;
private ICatRepository _catRepository;
private bool _disposed;
public UnitOfWork(string connectionString)
{
_connection = new SqlConnection(connectionString);
_connection.Open();
_transaction = _connection.BeginTransaction();
}
public IBreedRepository BreedRepository
{
get { return _breedRepository ?? (_breedRepository = new BreedRepository(_transaction)); }
}
public ICatRepository CatRepository
{
get { return _catRepository ?? (_catRepository = new CatRepository(_transaction)); }
}
public void Commit()
{
try
{
_transaction.Commit();
}
catch
{
_transaction.Rollback();
throw;
}
finally
{
_transaction.Dispose();
_transaction = _connection.BeginTransaction();
resetRepositories();
}
}
private void resetRepositories()
{
_breedRepository = null;
_catRepository = null;
}
public void Dispose()
{
dispose(true);
GC.SuppressFinalize(this);
}
private void dispose(bool disposing)
{
if (!_disposed)
{
if(disposing)
{
if (_transaction != null)
{
_transaction.Dispose();
_transaction = null;
}
if(_connection != null)
{
_connection.Dispose();
_connection = null;
}
}
_disposed = true;
}
}
~UnitOfWork()
{
dispose(false);
}
}
There are two intended ways to use transactions with Dapper.
Pass your IDbTranasction to your normal Dapper call.
Before:
var affectedRows = connection.Execute(sql, new {CustomerName = "Mark"});
After:
var affectedRows = connection.Execute(sql, new {CustomerName = "Mark"}, transaction=tx);
Use the new .Execute extension method that Dapper adds to IDbTransaction itself:
tx.Execute(sql, new {CustomerName = "Mark"});
Note: the variable tx comes from IDbTransaction tx = connection.BeginTransaction();
This is how you're supposed to use transactions with Dapper; neither of them are TranasctionScope.
Bonus Reading
https://stackoverflow.com/a/67474832/12597
I have a windows services which is performing lot of Data processing. At some point, my service is crashed on closing a SQLConnection. When I comment the Close connection method call, Service is working consistently without crashing.
What could be the problem ? Below is a code snippet
private void DeleteTempTable()
{
_logger.Info("DeleteTempTable");
try
{
foreach (KeyValuePair<string, string> item in _stables)
{
string dropSql = string.Empty;
dropSql = string.Format("DROP TABLE [{0}];", item.Value);
SqlConnection oConnDropTables = new SqlConnection(connectionString);
oConnDropTables.Open();
if (!string.IsNullOrEmpty(dropSql))
{
using (SqlCommand cmd = new SqlCommand(dropSql, oConnDropTables))
{
cmd.ExecuteNonQuery();
}
}
if (oConnDropTables != null && oConnDropTables.State == ConnectionState.Open)
oConnDropTables.Close();
oConnDropTables = null;
}
}
catch (Exception ex)
{
_logger.Error("Error " + ex.Message);
throw ex;
}
}
When I comment the Close connection, service is working without crashing. Also it is not caught in the catch block. Also Connection is not Null and connectionstate is open only..
What I have tried:
1) Put "using" construct for connection - Didn't help
2) catching SQLException to check if anything I get- Didn't help
Removing that Close() should not make any problems go away, and frankly I don't believe it has. Since you don't yet understand the problem, it is premature to assume that a random code change has fixed it. Specifically:
with the Close(), it is returning the connection to the pool each time; when you call Open(), it will get back the same connection from the pool (cleansed, except for a few minor things)
without the Close(), the previous connection will be left to be garbage collected, which can cause either the connection-pool to become saturated, or the database-server's connection count to saturate; basically - bad things
What I suspect is happening is that you had some random error, that you now aren't seeing, by random. For example, network connectivity, or the unpredictable ordering of a Dictionary<,> (which means you don't know what order the tables are being DROPped, which is very important if there are foreign keys between them).
The only major problem with the current code is that it isn't using using. There are some redundant lines, though. This would be better:
foreach (var item in _stables)
{
var dropSql = string.Format("DROP TABLE [{0}];", item.Value);
using(var oConnDropTables = new SqlConnection(connectionString))
using (var cmd = new SqlCommand(dropSql, oConnDropTables))
{
oConnDropTables.Open();
cmd.ExecuteNonQuery();
}
}
or (preferable):
using(var oConnDropTables = new SqlConnection(connectionString))
{
oConnDropTables.Open();
foreach (var item in _stables)
{
var dropSql = string.Format("DROP TABLE [{0}];", item.Value);
using (var cmd = new SqlCommand(dropSql, oConnDropTables))
{
cmd.ExecuteNonQuery();
}
}
}
The issue is the creation of a new connection object each time the loop runs. When you close a SQL Connection, it is not actually closed but its returned to the app pool ready to be re-used. There is a limited number of connections you can open in SQL at once.
Try moving the SQLConnection object out of the loop and just execute commands in the loop and close the connection after the loop finishes.
private void DeleteTempTable()
{
_logger.Info("DeleteTempTable");
try
{
using(SqlConnection oConnDropTables = new SqlConnection(connectionString))
{
oConnDropTables.Open();
foreach (KeyValuePair<string, string> item in _stables)
{
string dropSql = string.Empty;
dropSql = string.Format("DROP TABLE [{0}];", item.Value);
if (!string.IsNullOrEmpty(dropSql))
{
using (SqlCommand cmd = new SqlCommand(dropSql, oConnDropTables))
{
cmd.ExecuteNonQuery();
}
}
}
}
}
catch (Exception ex)
{
_logger.Error("Error " + ex.Message);
throw ex;
}
}
To test if i can connect to my database, I execute the following code :
using (SqlConnection connection = new SqlConnection(myConnectionString))
{
try
{
connection.Open();
canConnect = true;
}
catch (SqlException) { }
}
This works except it throws an exception if the connection failed. Is there any other way to test a Sql connection that doesn't throw an exception ?
Edit :
To add precision, i'm asking if there is a simple method that does that without having to open the connection and catch exceptions that can occur
When attempting to open a connection, there is no way to avoid the exception if the connection can't be opened. It can be hidden away in a function somewhere, but you're going to get the exception, no matter what.
It was designed like this because generally you expect to be able to connect to the database. A failed connection is the exception.
That being said, you can test the current connection state at any time by checking the State property.
write an extension like so:
public static class Extension{
public static bool CanOpen(this SqlConnection connection){
try{
if(connection == null){ return false; }
connection.Open();
var canOpen = connection.State == ConnectionState.Open;
connection.close();
return canOpen;
}
catch{
return false;
}
}
Then you can consume it like:
using(var connection = new SqlConnection(myConnectionString)){
if(connection.CanOpen()){
// NOTE: The connection is not open at this point...
// You can either open it here or not close it in the extension method...
// I prefer opening the connection explicitly here...
}
}
HTH.
If it throws an an exception and you handle it in your catch block you already know the connection failed. I think you answered your own question.
I think the real answer here is ping.
string data = "ismyserverpingable";
byte[] buffer = Encoding.ASCII.GetBytes (data);
int timeout = 120;
PingReply reply = pingSender.Send ("google.com", timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
}
Unless you are explicitly checking to see if a sql connection is possible 9/10 you should know if something is a sql server. This would save you that nasty memory usage of an exception which is what i am betting you are really after.
You can not avoid exception coming while connecting database but have some function which handle this very well. I am using this function which return true if connection exist.
public static bool IsSQLConnectionAvailable()
{
SqlConnection _objConn = new SqlConnection();
try
{
_objConn.ConnectionString = ConfigurationManager.ConnectionStrings["DefaultSQLConnectionString"].ConnectionString;
_objConn.Open();
}
catch
{
return false;
}
finally
{
if (_objConn.State == ConnectionState.Open)
_objConn.Close();
}
return true;
}
You could always use the ConnectionStringBuilder class and check for the existence of each piece that is required by a connection string before attempting to open it.
If the connection string is correct, but the database server you're connecting to is down, you're still going to get an excepton. Kind of pointless to check the quality of the string if the endpoint you're connecting to can potentially be offline.
I'd like to share the whole solution I've implemented to avoid checking the connection at every call. If the connection string is wrong an exception stops the execution, otherwise the attempt to open the connectionstring is done just once for each connectionstring.
Since the connection is often multithreaded I've added a syncobj used by the lock which checks
#if DEBUG
private static object syncobj = new object();
private static ConcurrentDictionary<string, bool> CheckedConnection = new ConcurrentDictionary<string, bool>();
private static void CheckCanOpenConnection(SqlConnection connection)
{
lock (syncobj)
{
try
{
CheckedConnection.TryGetValue(connection.ConnectionString, out bool found);
if (found)
{
return;
}
else
{
connection.Open();
var canOpen = connection.State == ConnectionState.Open;
connection.Close();
CheckedConnection.TryAdd(connection.ConnectionString, true);
return;
}
}
catch
{
throw new ApplicationException("Unable to connect to: " + connection.ConnectionString);
}
}
}
#endif
Here is the call to from the method which instantiate the connection
private SqlConnection CreateConnection()
{
if (_connection == null)
{
_connection = new SqlConnection(this.ConnectionString);
#if DEBUG
CheckCanOpenConnection(_connection);
#endif
}
return _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.