Performance comparison between using block and Dispose method - c#

Think about these 2 snippets:
Approach 1: use using statement
using(var connection = new SqlConnection())
using(var command = new SqlCommand(cmdText, connection)){
try{
connection.Open();
using(var reader = command.ExecuteReader(
CommandBehavior.CloseConnection | CommandBehavior.SingleResult){
while(reader.Read())
// read values
}
} catch (Exception ex) {
// log(ex);
}
}
Approach 2: use try/finally
var connection = new SqlConnection();
var command = new SqlCommand(cmdText, connection);
SqlDataReader = null;
try{
var reader = command.ExecuteReader(
CommandBehavior.CloseConnection | CommandBehavior.SingleResult);
while(reader.Read())
// read values...
} catch (Exception ex) {
// log(ex);
} finally {
command.Dispose();
if (reader != null) {
if (!reader.IsClosed)
reader.Close();
reader.Dispose();
}
if (connection.State != ConnectionState.Closed)
connection.Close();
connection.Dispose();
}
We all know that the using statements would be compiled to try/finally blocks. So is it correct to say: when the app get compiled, there would be 4 try blocks?
try { // for using SqlConnection
try { // for using SqlCommand
try { // my own try block
try { // for using SqlDataReader
} finally {
// dispose SqlDataReader
}
} catch {
// my own catch. can be used for log etc.
}
} finally {
// dispose SqlCommand
}
} finally {
// dispose SqlConnection
}
And, if the answer is yes, wouldn't that be a performance issue? Generally, is there any, I mean any performance difference between using blocks and try/finally blocks?
UPDATE:
From comments, I've to say:
1- The important question is, having multiple try blocks inside each other: is there any performance issue?
2- I have to care of code, because I'm responsible to code, not to query. The query-side has its own developer which is doing his best. So, I have to do my best too. So, it's important to me to take care of milliseconds ;) Thanks in advance.

Usually when you hear about try/catch is slow, it's all about exception handling. So if exception occurs then it might be slow. But just entering in try method is not something you should worry about. Especially in your case when you warp SQL query call.
If you want to know more about exceptions and performance in .NET you can find a lot of articles to read. For example: MSDN article or great CodeProject article.
And of course using is preferable way because it makes code much cleaner.

Related

Is it ok not to use using for transactions (in ADO.net)? Can I use snippet 2 instead of snippet 1? [duplicate]

I've been running into some problems concerning a SqlTransaction I'm using in my code. During my Googling I see many people using a using statement with a SqlTransaction.
What is the benefit and/or difference of using this type of statement with a SqlTransaction?
using (SqlConnection cn = new SqlConnection())
{
using (SqlTransaction tr = cn.BeginTransaction())
{
//some code
tr.Commit();
}
}
Currently my code looks like this:
SqlConnection cn = new SqlConnection(ConfigurationManager.AppSettings["T3"]);
cn.Open();
SqlTransaction tr = cn.BeginTransaction();
try
{
//some code
tr.Commit();
cn.Close();
}
catch(Exception ex)
{
tr.Rollback();
cn.Close();
throw ex;
}
What is the advantage of one way over the other?
A using statement should be used every time you create an instance of a class that implements IDisposable within the scope of a block. It ensures that the Dispose() method will be called on that instance, whether or not an exception is thrown.
In particular, your code only catches managed exceptions, then destroys the stack frame by throwing a new exception instead of rethrowing the existing one.
The correct way to do it is:
using (SqlConnection cn = new SqlConnection(ConfigurationManager.AppSettings["T3"])) {
cn.Open();
using (SqlTransaction tr = cn.BeginTransaction()) {
//some code
tr.Commit();
}
}
Note that if your class has instance members of types that implement IDisposable, then your class must implement IDisposable itself, and dispose of those members during its own Dispose() call.
The reason for this is that the SqlTransaction object will roll back in its Dispose() method if it was not explicitly committed (e.g. if an exception is thrown). In other words, it has the same effect as your code, just a little bit cleaner.
Essentially the using does the same thing that you are doing, except int a finally block instead of catching all exceptions:
using (SqlConnection cn = new SqlConnection())
{
using (SqlTransaction tr = cn.BeginTransaction())
{
//some code
tr.Commit();
}
}
is the same as, just much less code :)
{
SqlConnection cn = null;
try
{
cn = new SqlConnection();
{
SqlTransaction tr = null;
try
{
tr = cn.BeginTransaction())
//some code
tr.Commit();
}
finally
{
if(tr != null && tr is IDisposable)
{
tr.Dispose();
}
}
}
}
finally
{
if(cn != null && cn is IDisposable)
{
cn.Dispose();
}
}
}
In the end, using is just a shortcut for a pattern. But it's a very useful and helpful shortcut, because it ensures you implement the pattern correctly and means you can do it with less code.
In this case, you haven't implemented the pattern correctly. What happens in your code if the call to tr.RollBack() also throws an exception?
The using statement is closing and disposing your connection and transaction for you. It's the equivalent of having a finally block on your try/catch that does the dispose.
You could also condense the using blocks down a bit like this...
using (SqlConnection cn = new SqlConnection())
using (SqlTransaction tr = cn.BeginTransaction())
{
//some code
tr.Commit();
}
which would be roughly the same as:
SqlConnection cn = null;
SqlTransaction tr = null;
try
{
cn = new SqlConnection());
tr = cn.BeginTransaction());
//some code
tr.Commit();
}
finally
{
if (cn != null)
cn.Dispose();
if (tr != null)
tr.Dispose();
}
If you don't use a using() block, you'll have to explicitly call the .Dispose() method of the SqlConnection and SqlTransaction objects. If you fail to do that, then unmanaged resources will not be released and could cause memory leaks or other problems.
Using using gurantees that your connection object will be disposed after the code returns. Dispose is useful to release unmanages resources, As a good practice, if an object implements IDisposable, dispose method always should be called
In addition to all that, it prettifies your code. Doesn't the 7 lines of code look better than the 14 lines? I breath a sign of relief every time I see a using block. It's like that little squirt of mist that comes out of that glad smelly thing. Mmm, I'm a pretty block of efficient code. Look at how well I manage memory and how pleasing I am to the eye.

An exception can lead to the closing of a SqlConnection?

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

SqlCommand.ExecuteReader() does not throw SqlException when deadlocked

We're using C# SqlCommand.ExecuteReader() to issue SQL Server stored procedure and SQL requests inside a transaction.
When the connection is chosen as a deadlock victim, ExecuteReader() does NOT throw SqlException with 1205 deadlock code for some commands but DOES for others.
According to MSDN
If a transaction is deadlocked, an exception may not be thrown until Read is called.
Considering that we use SqlCommand object encapsulated inside our own database request framework, is there a way to always guarantee that the exception is thrown when a deadlock occurs?
We're using .Net 4.5, SQL Server 2008 R2, Visual Studio 2012
Here is a simplified version of our database access framework code:
SqlDataReader DoWork( string sql ) {
...
cmd = new SqlCommand( sql );
SqlDataReader rdr = null;
try {
rdr = cmd.ExecuteReader( CommandBehavior.Default );
} catch (SqlException sqle) {
// Log the error, throw a custom exception, etc.
// if (sqle.ErrorCode == 1205) ...
...
if (rdr != null) {
rdr.Close();
rdr = null;
}
}
// All is well, so just return to caller to consume the result set
return rdr;
}
...
main() {
...
SqlDataReader result = DoWork( "select ...";
if (result.HasRows) { // Check there is data to read...
while (result.Read()) {
...
}
result.Close();
...
}
I don't know why you are doing this:
if (result.HasRows)
This is not necessary and it prevents the deadlock from appearing:
If a transaction is deadlocked, an exception may not be thrown until Read is called.
Delete that if. It's a common anti pattern. It's often introduced by people who copy sample code without really understanding what it does.
This in your catch is also an anti pattern:
if (rdr != null) {
rdr.Close();
rdr = null;
}
Just use using.
this is the code from that link, Stack wouldnt allow it as an answer
function DoWork() {
using (TransactionScope scope = new TransactionScope(...)) {
cmd = new SqlCommand("select ...");
using (DataReader rdr = cmd.ExecuteReader ()) {
while(rdr.Read()) {
... process each record
}
}
scope.Complete ();
}
}

How should I correctly dispose of an object?

I frequently use the following code (or alike) to dispose of objects:
SqlCommand vCmd = null;
try
{
// CODE
}
catch(Exception ex) { /* EXCEPTION HANDLE */ }
finally
{
if (vCmd != null)
{
vCmd.Dispose();
vCmd = null;
}
}
Is this the best way to release objects and dispose of objects?
I'm using the VS analytics and give me a warning about redundancies. But I always do it this way...
The best way in terms of readability is using the using statement:
using(SqlCommand vCmd = new SqlCommand("...", connection)
{
try
{
// CODE
}
catch(Exception ex)
{
// EXCEPTION HANDLE
}
}
It disposes objects even in case of error, so similar to a finally. You should use it always when an object implements IDisposable which indicates that it uses unmanaged resources.
Further reading:
Cleaning Up Unmanaged Resources
there is no need to set objects to null.
Here is an example from MSDN:
private static void ReadOrderData(string connectionString)
{
string queryString =
"SELECT OrderID, CustomerID FROM dbo.Orders;";
using (SqlConnection connection = new SqlConnection(
connectionString))
{
SqlCommand command = new SqlCommand(
queryString, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}",
reader[0], reader[1]));
}
}
finally
{
// Always call Close when done reading.
reader.Close();
}
}
}
Note the use of "using" for the connection.
Back in the Olden Days of COM/ActiveX, you needed to set your objects to "Nothing".
In managed code, this is no longer necessary.
You should neither call "Dispose()", nor set your sqlCommand to "null".
Just stop using it - and trust the .Net garbage collector to do the rest.

Exception handling placement - C#

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

Categories