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;
}
Related
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;
}
}
}
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();
}
}
I need to validate the ConnectionString property on a DataContext object to ensure that LINQ can get a connection to the database. I have tried the two methods below but, they lock up the application if the connection string is invalid. Is there another way in LINQ to do this?
public static bool TestDBConnection(connectionString)
{
bool result = true;
DomainClassesDataContext db = new DomainClassesDataContext(connectionString);
try
{
// Hangs if connectionString is invalid rather than throw an exception
db.Connection.Open();
// Initially, I was just trying to call DatabaseExists but, this hangs as well if the conn string is invalid
if (!db.DatabaseExists())
{
result = false;
}
}
catch (Exception ex)
{
result = false;
logger.Fatal(ex.Message);
logger.Fatal(ex.StackTrace);
}
finally
{
db.Dispose();
}
return result;
}
Set the Connection Timeout in the connection string to a low value like 5s.
Opening is not enough. You might get a stale, pooled connection. Execute a query: SELECT NULL.
Here is a sample of the class I currently use for database interaction:
using System;
using System.Data;
using System.Collections.Generic;
// Libraries
using log4net;
using log4net.Config;
using MySql.Data.MySqlClient;
namespace AIC
{
class DB
{
private static readonly ILog _logger = LogManager.GetLogger(typeof(DB));
private MySqlConnection _connection;
private MySqlCommand _cmd;
private string _server;
private string _database;
private string _username;
private string _password;
//Constructor
public DB(string server, string database, string username, string password)
{
log4net.Config.XmlConfigurator.Configure();
_server = server;
_database = database;
_username = username;
_password = password;
_connection = new MySqlConnection(string.Format("SERVER={0};DATABASE={1};UID={2};PASSWORD={3};charset=utf8;", _server, _database, _username, _password));
}
public bool TestConnection()
{
try
{
_connection.Open();
_connection.Close();
_logger.Info("Connection test, passed...");
return true;
}
catch (MySqlException ex)
{
_logger.Error(ex.ToString());
return false;
}
}
//open connection to database
private bool Open()
{
try
{
if (_connection.State != ConnectionState.Open)
_connection.Open();
_logger.Info("Starting connection to database...");
return true;
}
catch (MySqlException ex)
{
_logger.Error(ex.ToString());
return false;
}
}
//Close connection
private bool Close()
{
try
{
if (_connection.State != ConnectionState.Closed)
_connection.Close();
_logger.Info("Closing connection to database...");
return true;
}
catch (MySqlException ex)
{
_logger.Error(ex.ToString());
return false;
}
}
// Some basic functions
public bool UserExist(string user)
{
string query = "SELECT user_id FROM users WHERE username=#name LIMIT 1";
if (this.Open())
{
try
{
// Assign the connection
_cmd = new MySqlCommand(query, _connection);
// Prepare to receive params
_cmd.Prepare();
// Fill up the params
_cmd.Parameters.AddWithValue("#name", user);
// returned count bool
bool result = Convert.ToInt32(_cmd.ExecuteScalar()) > 0;
// Close connection
this.Close();
return result;
}
catch (MySqlException ex)
{
_logger.Error(ex.ToString());
this.Close();
return false;
}
}
else
{
_logger.Error("You must be connected to the database before performing this action");
return false;
}
}
public bool AddUser(string user)
{
// .... add user to database
}
public bool DelUser(string user)
{
// .... del user from database
}
public int CountUsers()
{
// .... count total users from database
}
}
}
Currently, I don't have any management for opening and closing the connections so it will always check wether the database is connected or not, perform the action and close it as shown in the UserExist function.
Considering this, it came to my attention that I might be closing my own connections in the middle or their transactions since I am using this in 2 different threads.
My doubt here is wether this simple class could lock my application for any reason making it unresponsive or cause me any troubles in the long run?
What should I consider, improve, etc.?
Would appreciate code samples.
Each thread should have its own connection instance, in your case probably an instance of Db.
But the problem would be solved (a lot) better by not storing a connection in your Db objects at all. The best pattern is to only use connections as local variables in a using() {} statement.
Currently, your class should implement IDisposable (just for the case where your try/catch logic fails).
Waiting for exceptions to be thrown and then handle them is not a good way for design a multithreading class. a good design will be with using lock statement. when using a lock you are providing a critical regions so only one thread is allowed to access to the resources at time. once one thread finish its usage the other can proceed and so on.
For example:
so it will always check wether the database is connected or not, perform the action and close
what will happen if two threads try to enter to the same method concurrently? one thread checking if the connection is not set to continue and it finds that the connection is not set so it proceed. but at the middle of its process and before it connects, the Thread Context Switching switches to the other thread and pause the first one, the second thread in turn ask if the connection was set and it will find that it is not, so it connect and proceed. Now the thread context switching switches to the first thread to continue its execution. and the problems begins...
But the scenario is different when using 'lock'; One and only one thread will allowed to access to the method region that marked with the lock. So one thread enter the lock region and establish the connection. at that time the other thread try to access to the method but the first one is still there so the second will be waiting until the first one finishes its work and then it will proceed.
You don't have to lock them, but yes: you must ensure 2 threads aren't using the same connection at the same time.
Synchronisation (locks, etc) is one way to do that; isolation is another (better, IMO) way. If two threads never have the same connection then all is good. For this reason, a static connection is never a good idea.
Using the TransactionScope object to set up an implicit transaction that doesn't need to be passed across function calls is great! However, if a connection is opened whilst another is already open, the transaction coordinator silently escalates the transaction to be distributed (needing MSDTC service to be running and taking up much more resources and time).
So, this is fine:
using (var ts = new TransactionScope())
{
using (var c = DatabaseManager.GetOpenConnection())
{
// Do Work
}
using (var c = DatabaseManager.GetOpenConnection())
{
// Do more work in same transaction using different connection
}
ts.Complete();
}
But this escalates the transaction:
using (var ts = new TransactionScope())
{
using (var c = DatabaseManager.GetOpenConnection())
{
// Do Work
using (var nestedConnection = DatabaseManager.GetOpenConnection())
{
// Do more work in same transaction using different nested connection - escalated transaction to distributed
}
}
ts.Complete();
}
Is there a recommended practise to avoid escalating transactions in this way, whilst still using nested connections?
The best I can come up with at the moment is having a ThreadStatic connection and reusing that if Transaction.Current is set, like so:
public static class DatabaseManager
{
private const string _connectionString = "data source=.\\sql2008; initial catalog=test; integrated security=true";
[ThreadStatic]
private static SqlConnection _transactionConnection;
[ThreadStatic] private static int _connectionNesting;
private static SqlConnection GetTransactionConnection()
{
if (_transactionConnection == null)
{
Transaction.Current.TransactionCompleted += ((s, e) =>
{
_connectionNesting = 0;
if (_transactionConnection != null)
{
_transactionConnection.Dispose();
_transactionConnection = null;
}
});
_transactionConnection = new SqlConnection(_connectionString);
_transactionConnection.Disposed += ((s, e) =>
{
if (Transaction.Current != null)
{
_connectionNesting--;
if (_connectionNesting > 0)
{
// Since connection is nested and same as parent, need to keep it open as parent is not expecting it to be closed!
_transactionConnection.ConnectionString = _connectionString;
_transactionConnection.Open();
}
else
{
// Can forget transaction connection and spin up a new one next time one's asked for inside this transaction
_transactionConnection = null;
}
}
});
}
return _transactionConnection;
}
public static SqlConnection GetOpenConnection()
{
SqlConnection connection;
if (Transaction.Current != null)
{
connection = GetTransactionConnection();
_connectionNesting++;
}
else
{
connection = new SqlConnection(_connectionString);
}
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
return connection;
}
}
Edit: So, if the answer is to reuse the same connection when it's nested inside a transactionscope, as the code above does, I wonder about the implications of disposing of this connection mid-transaction.
So far as I can see (using Reflector to examine code), the connection's settings (connection string etc.) are reset and the connection is closed. So (in theory), re-setting the connection string and opening the connection on subsequent calls should "reuse" the connection and prevent escalation (and my initial testing agrees with this).
It does seem a little hacky though... and I'm sure there must be a best-practise somewhere that states that one should not continue to use an object after it's been disposed of!
However, since I cannot subclass the sealed SqlConnection, and want to maintain my transaction-agnostic connection-pool-friendly methods, I struggle (but would be delighted) to see a better way.
Also, realised that I could force non-nested connections by throwing exception if application code attempts to open nested connection (which in most cases is unnecessary, in our codebase)
public static class DatabaseManager
{
private const string _connectionString = "data source=.\\sql2008; initial catalog=test; integrated security=true; enlist=true;Application Name='jimmy'";
[ThreadStatic]
private static bool _transactionHooked;
[ThreadStatic]
private static bool _openConnection;
public static SqlConnection GetOpenConnection()
{
var connection = new SqlConnection(_connectionString);
if (Transaction.Current != null)
{
if (_openConnection)
{
throw new ApplicationException("Nested connections in transaction not allowed");
}
_openConnection = true;
connection.Disposed += ((s, e) => _openConnection = false);
if (!_transactionHooked)
{
Transaction.Current.TransactionCompleted += ((s, e) =>
{
_openConnection = false;
_transactionHooked = false;
});
_transactionHooked = true;
}
}
connection.Open();
return connection;
}
}
Would still value a less hacky solution :)
One of the primary reasons for transaction escalation is when you have multiple (different) connections involved in a transaction. This almost always escalates to a distributed transaction. And it is indeed a pain.
This is why we make sure that all our transactions use a single connection object. There are several ways to do this. For the most part, we use the thread static object to store a connection object, and our classes that do the database persistance work, use the thread static connection object (which is shared of course). This prevents multiple connections objects from being used and has eliminated transaction escalation. You could also achieve this by simply passing a connection object from method to method, but this isn't as clean, IMO.