I have a C# database layer that with static read method that is called every second in background timer.
currently I create SqlCommand, SqlConnection once as a class memeber.
In every method call I execute the command to get the results,I am doing so to avoid creation of connection and command every second, but I am afraid from exception occurs in this method that will break the connection or put the object in the invalid state.
This is my current implementation (Timer Handler)
static void GetBarTime(object state)
{
lock (_staticConnection)
{
SqlDataReader dataReader = null;
try
{
dataReader = _getMaxTimeCommand.ExecuteReader();
dataReader.Read();
_currentTick = dataReader.GetInt32(0);
}
catch (Exception ex)
{
//Log the error
}
finally
{
dataReader.Dispose();
}
}
}
What is the best practise?
MORE DETAILS:
I am doing this in a timer as there is another prorcess update my table every second, and there is another exposed method used by set of clients and called every second to get the latest value.
So instead of executing select statement every second for each client, I am doing it in a timer and update global variable that is used by the clients.
SqlConnection has pooling built in; you would see almost no difference if you used:
using(SqlConnection conn = new SqlConnection(connectionString)) {
conn.Open();
// your code
}
each time. And that can react automatically to dead (underlying) connections.
Currently you have a bug, btw; if the command fails, the reader will still be null... either check for null before calling Dispose():
if(dataReader !=null) {dataReader.Dispose();}
or just use using:
try
{
using(SqlDataReader dataReader = _getMaxTimeCommand.ExecuteReader())
{
dataReader.Read();
_currentTick = dataReader.GetInt32(0);
}
}
catch (Exception ex)
{
//Log the error
}
It can be pretty difficult to find out if an execption means that the connection is a dead duck. To be on the safe side, you could close and reopen the SqlConnection and SqlCommand whenever you encounter an exception, just in case. That doesn't cause any overhead when everything works alright.
Related
I have created a class in my program to handle database connection. This class includes a method named OpenConnection() to open the connection to the database. I'm not convinced that my program meets the standard of clean code. Here is the method.
public void OpenConnection()
{
if(connection==null || connection.State != Connection.Open)
{
connection = new OracleConnection(this.connectionString);
connection.Open();
}
}
This method works okay but I just want to make sure if this is a safe way and I am not exploiting my program in any way. Thank You in advance
Update
I also added the following methods in the class to close the connection and dispose it.
public void CloseConnection()
{
if (dbconnect != null | dbconnect.State != ConnectionState.Closed)
{
dbconnect.Close();
}
}
//Here the IDsiposable method is implemented
public void Dispose()
{
CloseConnection();
}
You can use using clause and it's going to handle the Dispose automatically.
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command = new SqlCommand("UpdateEmployeeTable", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#EmployeeID", 123));
command.CommandTimeout = 5;
command.ExecuteNonQuery();
connection.close();
}
Your solution as coded seems ok if you add the cases suggested in this answer and if it's meant to be used on a single thread and within a very limited scope. That said it appears like you are gearing up to use this class as a parameter across many method calls because you want to
mix business logic and persistence concerns
or share an instance in such a way that other methods don't have to be concerned about whether to open the connection (e.g. a higher call in the call stack has not yet called Open) or not (e.g. a prior call in the call stack did open the connection (what we'd call an "ambient" connection)).
Either of these strategies usually leads to trouble. It's better to keep the scope small, where you know the connection is open and when to close it:
using (var connection = new OracleConnection(...))
{
connection.Open();
...
}
When you have this small scope, your abstraction now provides no value.
You have a possible resource leak owing to the fact that OracleConnection implements IDisposable. Also, calling close on a connection in ConnectionState.Executing or Fetching could be bad as it will rollback all uncommitted transactions.
public void OpenConnection()
{
if (connection == null)
{
connection = new OracleConnection(this.connectionString);
connection.Open();
return;
}
switch (connection.State)
{
case ConnectionState.Closed:
case ConnectionState.Broken:
connection.Close();
connection.Dispose();
connection = new OracleConnection(this.connectionString);
connection.Open();
return;
}
}
I'm building the treatment of a connection and came this question in mind, but I could not find a satisfactory answer. Then I come here to ask more experienced programmers. Is there any possibility that an exception can lead to the closing of an already opened SqlConnection?
illustrative code:
SqlConnection con = new SqlConnection(connectionString);
con.Open();
try
{
// some code that can throw an exception here....
}
catch (Exception)
{
// is there any possibility of this error close the connection?
}
Is there any possibility of an exception lead to the closing of an
already open SqlConnection?
Exceptions will not voluntarily close an open SqlConnection. In all instances, you have to take care of its resources. You can do this by explicitly calling the Close() method (best in a finally block), or wrapping it in a using statement (this technique is often preferred).
Explicitly calling .Close()
SqlConnection con = new SqlConnection(connectionString);
con.Open();
try
{
//some code that can throw an exception here....
}
catch (Exception)
{
//is there any possibility of this error close the connection? no
}
finally
{
//call close here - finally block will always execute
con.Close();
}
Using statement
using (SqlConnection con = new SqlConnection(connectionString)) {
con.Open();
try
{
//some code that can throw an exception here....
}
catch (Exception)
{
//is there any possibility of this error close the connection? no
}
//Close() is taken care of by the using statement
}
Also, I'd recommend putting your Open() call inside your try-catch as it can throw an exception.
Edit:
In case you're unsure about what the using statement does:
Provides a convenient syntax that ensures the correct use of
IDisposable objects.
You can read more about it in MSDN's documentation
I have some problems with my database connection in my application.
My application stores some data into a mysql database and now I got the error mentioned in the title.
The problem is:
Right before I call the method that throws this exception I call another method which also connects to the database but successfully.
At first I thought that there is an error in my source but there is no error.
Here is the bad method:
public static bool checkExistence(object obj)
{
MySqlCommand checkQuery = new MySqlCommand(MySQLQueries.getCheckQueryByObject(obj), connection);
object checkResult = null;
if (connection.State == System.Data.ConnectionState.Closed)
{
OpenConnection();
try
{
checkResult = checkQuery.ExecuteScalar();
}
catch (MySqlException ex)
{
ErrorHandler(ex);
return true;
}
catch (Exception ex)
{
ErrorHandler(ex);
return true;
}
finally
{
CloseConnection();
}
}
else
{
checkResult = checkQuery.ExecuteScalar();
}
if (checkResult != null)
return true;
else
return false;
}
As you can see I first create a new command which later will check if an object exists.
The result of the query will be stored in object checkResult and at the end I simply check if checkResult == null.
Because of some problems with opening / closing the connection I decided to check if the connection is opened or not.
Now if the bad method is called the connection is closed.
Then after calling OpenConnection() the connection is opened again with the same settings as before.
As soon as the application executes checkResult = checkQuery.ExecuteScalar(); the exception is thrown.
I really don't know what actually is the problem.
To ensure that the connection is valid from my point of view I put connection into the watchlist and tracked every change made to it by the application.
Nothing was different than in any other method that successfully used the database.
A friend of mine said that there might be a kind of optimization error while building the application.
He himself doesn't work with C# but sometime with C so it was just a vague guess.
Is there maybe any error in the code that I missed or any guess why this happens?
Thanks in advance!
Greetz
Edit: I use the latest version of MySQL's C# connector
This is going to take some explaining. I'm new to ASP, having come from PHP. Completely different world. Using the MySql Connecter/Net library, I decided to make a database wrapper which had a fair amount of fetch methods, one being a "FetchColumn()" method which simply takes a string as its parameter and uses the following implementation:
public object FetchColumn(string query)
{
object result = 0;
MySqlCommand cmd = new MySqlCommand(query, this.connection);
bool hasRows = cmd.ExecuteReader().HasRows;
if (!hasRows)
{
return false;
}
MySqlDataReader reader = cmd.ExecuteReader();
int count = 0;
while(reader.HasRows)
{
result = reader.GetValue(count);
count++;
}
return result;
}� return result;
}public object FetchColumn(string query)
What I'm looking for is a way to return false IF and only IF the query attempts to fetch a result which doesn't exist. The problem is that, with my implementation, it throws an error/exception. I need this to "fail gracefully" at run time, so to speak. One thing I should mention is that with this implementation, the application throws an error as soon as the boolean "hasRows" is assigned. Why this is the case, I have no idea.
So, any ideas?
It's hard to say for sure, since you didn't post the exact exception that it's throwing, but I suspect the problem is that you're calling ExecuteReader on a command that is already in use. As the documentation says:
While the MySqlDataReader is in use, the associated MySqlConnection is busy serving the MySqlDataReader. While in this state, no other operations can be performed on the MySqlConnection other than closing it. This is the case until the MySqlDataReader.Close method of the MySqlDataReader is called.
You're calling cmd.ExecuteReader() to check to see if there are rows, and then you're calling ExecuteReader() again to get data from the rows. Not only does this not work because it violates the conditions set out above, it would be horribly inefficient if it did work, because it would require two trips to the database.
Following the example shown in the document I linked, I'd say what you want is something like:
public object FetchColumn(string query)
{
MySqlCommand cmd = new MySqlCommand(query, this.connection);
MySqlDataReader reader = cmd.ExecuteReader();
try
{
bool gotValue = false;
while (reader.Read())
{
// do whatever you're doing to return a value
gotValue = true;
}
if (gotValue)
{
// here, return whatever value you computed
}
else
{
return false;
}
}
finally
{
reader.Close();
}
}
I'm not sure what you're trying to compute with the HasRows and the count, etc., but this should get you pointed in the right direction.
you need to surround the error throwing code with a try clause
try {
//The error throwing Code
}
catch (exception e)
{
//Error was encountered
return false
}
If the error throwing code throws and error the catch statement will execute, if no error is thrown then the catch statement is ignored
First of all do a try and catch
try
{
//code
}
catch (Exception exp)
{
//show exp as message
}
And the possible reason of your error is that your mysql query has errors in it.
try executing your query directly in your mysql query browser and you'll get your answer.
If its working fine then double check your connection string if its correct.
NOTE:mark as answer if it solves your issue
I've decided to remove some of the using statements in my code so I can catch specific exceptions and handle the disposing of resources manually. I have refactored some of the code to make it more readable and maintable, after implementing the new try/catch block I am left wondering if they have been placed correctly for the task at hand.
Example:
public static DataTable Select(string table, string[] column, Object operand)
{
DataTable dTable = null;
SQLiteConnection connection = null;
SQLiteCommand command = null;
SQLiteDataReader dReader = null;
//convert to array for arguments
StringBuilder query = new StringBuilder();
query.Append("select ");
for (int i = 0; i < column.Length; i++)
{
query.Append(column[i]);
if (i < column.Length - 1)
{
query.Append(",");
}
}
query.Append(" from ");
query.Append(table);
try
{
connection = new SQLiteConnection(_connectionString);
command = new SQLiteCommand(query.ToString(), connection);
dTable = new DataTable();
connection.Open();
dReader = command.ExecuteReader();
dTable.Load(dReader);
return dTable;
}
catch (SQLiteException sqle)
{
//Handle exception
}
finally
{
connection.Dispose();
command.Dispose();
dReader.Dispose();
dTable.Dispose();
}
return null;
}
In this example I have only implemented the try/catch around the SQL operations themselves, I did this as it ensures any exceptions that are thrown can be noted and the resourced disposed correctly. I then noticed that this left the for loop open to exceptions, although the supplied indexer will be protected and created via a GUI.
Would I be wise to encapsulate the entire method in the try/catch statement or am I being overly cautious? You could say I'm looking for the best practice when it comes to managing the placement of the statements themselves.
Thanks for your time!
Edit:
I know that the using statement would be ideal in terms of handling the disposal and management of resources however as mentioned at the beginning of the question I wish to be able to catch specific types of exceptions, in particular those generated from the SQLite components.
Don't forget a null check:
finally {
if (connection != null) connection.Dispose();
if (command != null) command.Dispose();
if (dReader != null) dReader.Dispose();
if (dTable != null) dTable.Dispose();
}
It is possible that one of the constructors throws an exception, in that case the objects will not have been initialized.
Why use try/catch explicitly when what you are concerned about is resource management? Use using instead:
using(SQLiteConnection connection = new SQLiteConnection(_connectionString))
{
..
using(SQLiteCommand command = new SQLiteCommand(query.ToString(), connection))
{
using(SQLiteDataReader reader = dReader = command.ExecuteReader())
{
dTable.Load(dReader);
}
}
}
Also currently you are returning dTable, but you are disposing it in your finally block.
You could enclose the entire method in a try/catch if you think that there's any likelihood that exceptions will be thrown outside of the scope of database problems. You can easily differentiate the exceptions by what you catch. For example:
DataTable dTable = null;
SQLiteConnection connection = null;
SQLiteCommand command = null;
SQLiteDataReader dReader = null;
try
{
// non-DB code
// DB code
}
catch (SQLiteException sqle)
{
// Handle DB exception
}
catch (IndexOutOfRangeException ie)
{
// If you think there might be a problem with index range in the loop, for example
}
catch (Exception ex)
{
// If you want to catch any exception that the previous catches don't catch (that is, if you want to handle other exceptions, rather than let them bubble up to the method caller)
}
finally
{
// I recommend doing some null-checking here, otherwise you risk a NullReferenceException. There's nothing quite like throwing an exception from within a finally block for fun debugging.
connection.Dispose();
command.Dispose();
dReader.Dispose();
dTable.Dispose();
}
return null;
A bigger problem you've introduced with this refactoring can be seen when you consider what will happen when the creation of one of the intermediate entities fails. For example, if the connection creation throws, then what happens to the exception thrown in your finally block that attemts to call Dispose on all those null variables? At least check for null beforehand, or put an additional try/catch inside your finally. I'd say you could benefit from the use of Resharper, which would have already pointed out these issues.
I don't know if it is best practice but I usually put try/catch statements around blocks of code where external resources are accessed like database access, file I/O, etc. which might spit out exceptions due to various reason (inaccessible resource, I/O error, etc.). I don't protect code which I'm in control of - that's where unit tests come into place
Btw: You know that you can replace your loop with string.Join()?
Update: Just to clarify: try/catch blocks only really make sense if you want to catch specific exception and execute some custom logic. Otherwise you should stick to using and let the exception bubble up and deal with it at the appropriate place (e.g. notify the user that some data could not be saved because the server is unavailable or so)
If all you are worried about is properly disposing of things, you should be using a 'using' block for this. http://msdn.microsoft.com/en-us/library/yh598w02.aspx