Let's assume i got this code:
internal static bool WriteTransaction(string command)
{
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
try
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(command, conn))
cmd.ExecuteNonQuery();
}
catch { return false; }
}
return true;
}
Well, i have placed conn's using outside the try/catch clause because SqlConnection's constructor will not throw any exception (as it says). Therefore, conn.Open() is in the clause as it might throw some exceptions.
Now, is that right coding approach? Look: SqlCommand's constructor does not throw exceptinos either, but for the code reduction i've placed it along with cmd.ExecuteNonQuery() both inside the try/catch.
Or,
maybe this one should be there instead?
internal static bool WriteTransaction(string command)
{
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
try { conn.Open(); }
catch { return false; }
using (SqlCommand cmd = new SqlCommand(command, conn))
try { cmd.ExecuteNonQuery(); }
catch { return false; }
}
return true;
}
(sorry for my english)
Unless you can handle the exception in some meaningful way, do not catch it. Rather, let it propagate up the call-stack.
For instance, under what conditions can a SqlCommand ExecuteNonQuery() throw exceptions? Some possibilities are sql query that is improperly formed, cannot be executed or you've lost connection to the database server. You wouldn't want to handle these all the same way, right?
One exception you should consider handling is the SQLException deadlock (erro number 1205).
As was pointed out in a comment, at the very minimum you should be logging exceptions.
[BTW, WriteTransaction() is probably a poor name for that method, given the code you have shown.]
Your first code sample, with a single try-catch block, is equivalent to the second. The first one is, however, easier to read and shorter.
It's worth bearing in mind that the usual C# coding approach is not to catch exceptions except at the very top layer of your code.
A well-written reference on this is here: http://www.codeproject.com/KB/architecture/exceptionbestpractices.aspx.
In your case this will simplify your code: instead of returning a bool to indicate that the method succeeded or failed, then testing for this, you "assume for the best" by making the method void and merely handle unexpected exceptions at a top level exception handler.
Exception handling for writing to databases can be considered a slight exception to this general rule: but my personal approach would be to trap specifically for concurrency issues and if that happens retry a few times.
I think your first solution is better because if you get an error establishing connection is not useful trying to execute a command on that connection.
So with first solution if you get an error you go directly do catch block and then dispose objects, while with the second you go through two exceptions, overloading memory useless.
with good catch clause (exceptions logging) you don't realy need 2x try block, 1 is enough
...
your second approach is wrong - there's no need to try catch openning connection - becouse even if you catch this you are done anyway - you can't execute query. In your catch block you could try to "repair" that problem, but what would it give you - while loops in catch ?
Your first approach is the preferable one, for a very simple reason: The two versions of the method are identical in terms of behavior, but the first one needs less code.
Sometimes it's as simple as counting lines of code ;-)...
HTH!
P.S.
I wouldn't have a try/catch statement in this method at all, but I would place it on a higher level, where this internal method is invoked.
Given your method 'WriteTransaction' is swallowing all exceptions and returning the success of the transaction, or not, then I would use one try/catch block around the entire method.
internal static bool WriteTransaction(string command) {
try {
using (SqlConnection conn = new SqlConnection(SqlConnectionString)) {
conn.Open();
using (SqlCommand cmd = new SqlCommand(command, conn)) {
cmd.ExecuteNonQuery();
}
}
}
catch {
return false;
}
return true;
}
Now you should ask yourself if catching all exceptions and returning true/false is the right thing to do. When in production how are you going to diagnose and fix errors if you haven't at least logged the exception?
Related
sc is a SQL connection passed in from the calling function
I'm using one SQL connection throughout my entire program and having each subfunction open and close it as needed. (I read this was fine, because the SQLConnection class has it's own connection pooling functionality)
string q = "this would be a query";
using (SqlCommand cmd = new SqlCommand(q, sc))
{
cmd.Parameters.Add("#ID", SqlDbType.Int);
cmd.Parameters["#ID"].Value = (an id that is passed in);
try
{
sc.Open();
using (var reader = cmd.ExecuteReader())
{
if(reader.read())
{ logic that might throw exception }
else
{ logic that might throw exception }
}
sc.Close();
}
catch (Exception e)
{
alert user, program does not halt but current function returns
}
}
So the connection opens and the command attempts to execute and some logic is performed that might throw an exception. (I'm not expecting it to) This function is part of a larger program that is processing a large dataset. If it fails DUE TO AN EXCEPTION it needs to note it, but it also needs to attempt to keep running.
Other parts of the program are sharing this connection and opening and closing it as they need it and I've used this basic template for all queries in the program.
It just occurred to me that if an exception occurred, the connection might not be closed. Am I correct in thinking that? My original concern when writing this is that the sc.Open() would be the thing that would throw an exception, but as I've used this in multiple places I've realized that this was short sighted because the connection could open and then any number of steps between the close could throw an exception.
Do I need additional logic here to make sure this connection is closed and the program can attempt to continue running?
If my understanding is correct that the connection needs to be closed in the event of an exception between the open and close I think I have 2 options :
try/catch between the open and close
sc.Close() in the catch block (Bonus concern : If the sc.Open() throws an exception and catch block tries to sc.Close() will an additional exception be thrown?)
You do not need to worry about closing the connection. The connection is closed automatically when it disposed by the using statement within which the connection is created.
In the event of an exception, the connection will still be disposed (and thus closed) because that's how a using statement is designed to work.
You have the State property of the SqlConnection that you can use to determine what state the last network operation left the connection in. This property is described here: https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.state(v=vs.110).aspx
I would recommend reacting to exceptions in the SqlConnection (such as Open) and in the SqlCommand separately, because, in my experience, you will usually want to take different actions. Even with the overall approach you want to take,
if you can't open your connection, there is no point in preparing the query,
and you likely want to say something different about inability to open the connection than you would if the query failed. I would move the sc.Open() before the creation of the SqlCommand and try/catch around that.
Clarification on the above answer by #roryap - there is no need for sc.Close() if your connection is created in a using statement but from your question I guess it's not. In which case you should probably add a finally section to the try catch block and close the connection in there.
Its better that you close the connection in finally block
finally
{
sc.Close();
}
After try block is completed, the finally block will work.
In a case of an exception, finally block also works.
So the connection will closed in any case.
Does using keyword catch or handle exceptions in C# when connecting to a database? Or should I use try catch block in all of my database methods inside the using? Does using try catch create unnecessary code?
using (var db = new ApplicationContext())
{
try {
/* Query something */
} catch(Exception e) {
logger.Debug(e);
}
}
Does using keyword catch or handle exceptions in C# when connecting to a database?
A using is logically equivalent to a try-finally, so yes, it handles exceptions, but it does not stop the exception. A finally propagates the exception.
should I use try catch block in all of my database methods inside the using?
No. The try-catch should go outside the using. That way it will protect the resource creation.
Does using try catch create unnecessary code?
I have no idea what this question means.
Some questions you did not ask:
Should I catch all exceptions for logging and then fail to re-throw them?
No. Only catch and eat exceptions that you know how to handle. If you want to log exceptions then re throw them when you're done logging; other code might want to handle them.
What is the correct way to write this code?
Separate your concerns. You have three concerns:
Dispose the resource
Log all exceptions
Handle expected exogenous exceptions
Each of those should be handled by a separate statement:
try // handle exogenous exceptions
{
try // log all exceptions
{
using(var foo = new Foo()) // dispose the resource
{
foo.Bar();
}
}
catch(Exception x)
{
// All exceptions are logged and re-thrown.
Log(x);
throw;
}
}
catch(FooException x)
{
// FooException is caught and handled
}
If your goal is to only log unhandled exceptions then invert the nesting of the two handlers, or use another mechanism such as the appdomain's unhandled exception event handler.
The using block does not "handle" exceptions for you, it only ensures that the Dispose() method gets called on the IDisposable object (in this case, your db instance), even in the event of an exception. So yes, you need to add try-catch blocks where needed.
That said, in general, you only want to catch exceptions where you can actually do something meaningful with them. If you only need to log the exceptions, consider doing your exception handling in a single location higher in the call stack so that you don't have to litter your code with try-catch blocks all over the place.
You can read about the using Statement here to see what it actually does, and how it gets translated.
EDIT:
If, for whatever reason, you choose to keep your try-catch block where it is, at the very least, make sure to rethrow the exception instead of swallowing it, which would be like sweeping the mess under the rug and pretending everything is fine. Also, make sure to rethrow it without losing your precious stack trace. Like this:
using (var db = new ApplicationContext())
{
try {
/* Query something */
} catch(Exception e) {
logger.Debug(e);
throw; // rethrows the exception without losing the stack trace.
}
}
EDIT 2: Very nice blog entry by Eric Lippert about exception handling.
Your using will converts to bottom code by the C# compiler, by 8.13 The using statement:
{
var db = new ApplicationContext();
try
{
try {
/* Query something */
} catch(Exception e) {
logger.Debug(e);
}
}
finally
{
// Check for a null resource.
if (db!= null)
// Call the object's Dispose method.
((IDisposable)myRes).Dispose();
}
}
So, my opinion, for your situation I think better without using statement, it will be a little bit clear and will have less steps:
var db = new ApplicationContext();
try
{
/* Query something */
}
catch(Exception e)
{
logger.Debug(e);
}
finally
{
if (db!= null)
{
((IDisposable)myRes).Dispose();
}
}
Because using it's just a syntax sugar.
P.S: The performance cost of try statement is very small and you can left your code as it is.
The using keyword is used to that after the block finishes, the object inside the using parameter, in this case, the context, is disposed of properly, and so yes, you still need to use try-catch keywords for handling exceptions.
Since using does not handle any exception, you may want to swap.
using is syntactic sugar for try-finally so you know that, even if exception is not handled on constructor, connection will be either closed or not established at all.
try {
using (var db = new ApplicationContext())
{
/* Query something */
}
} catch(Exception e) {
logger.Debug(e);
}
I am working on a new project and have a section of code where I don't want to actually handle exceptions but make sure any DB connections are closed. I am wondering which will be the best way to handle the issue. I see 2 ways but am not sure which will be clearer:
SqlConnection con = new SqlConnection(connectionstring);
try
{
con.open()
//DoStuff
}
catch(Exception)
{
throw;
}
finally
{
con.close();
con.dispose();
}
OR
try
{
con.open()
//DoStuff
}
finally
{
con.close();
con.dispose();
}
Either way I pass the exception up to the calling code to be handled but still clean up the connections.
You can use using statement to enclose your connection. It would translate into try-finally block, like in your second code example.
Since you are not doing anything with your exception (like logging) you can leave out the catch block.
You can use using like:
using (SqlConnection con = new SqlConnection(connectionstring))
{
}
This will ensure your connection is disposed at the end of using block, even in case of an exception. You can only use using statement with those objects which implements IDisposable interface.
If you are going to deal with objects which doesn't implement IDisposable then your second code snippet (With try-finally) is good enough, since you want the exception to bubble up.
I'm finding that I'm having some website connection pool issues and I'm in the process of tracking them down. I know one thing to look for is to make sure that any SQLDataReaders get closed and I've gone though and made sure they are. One question that popped up in my head was about methods that return SQLDataReaders and how they get closed (or not).
So here's how I have things setup and some example methods:
public static SqlDataReader ExecuteReader(SqlCommand cmd)
{
SqlConnection c = new SqlConnection(Properties.Settings.Default.DatabaseConn);
cmd.Connection = c;
c.Open();
return cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
}
then I have a method that uses the 'ExecuteReader()'
public static SqlDataReader GetData()
{
SqlCommand Query = new SqlCommand("select * from SomeTable");
return ExecuteReader(Query);
}
Now say I have another method that calls 'GetData'. I simplified things obviously.
public static SqlDataReader GetMoreData()
{
return GetData;
}
So my question is, when I call 'GetMoreData' like this
SqlDataReader dr = GetMoreData();
//do some stuff with 'dr'
dr.close();
Are all my SqlDataReaders and connections being closed properly?
Thanks!
Description
The SqlDataReader implements the IDisposable interface.
On every class that implements IDisposable you should call Dispose or use using
in order to free resources, in this case close the reader and the underlying connection.
IDisposable Interface Defines a method to release allocated resources.
Sample
using(SqlDataReader dr = GetMoreData())
{
try
{
// do your stuff
}
catch(Exception ex)
{
// handle the exception
}
} // the reader will get closed here
or
SqlDataReader dr;
try
{
dr = GetMoreData();
// do your stuff
}
catch(Exception ex)
{
// handle the exception
}
finally
{
// close the reader
dr.Dispose();
}
Edit
Nice comment by JotaBe
but if he implements a method that returns a DataReader, the using should be used int the method's caller. So there's no way to warranty that the DataReader is closed.
I dont recommend to return a SqlDataReader but if you want to do this you need to do this
SqlDataReader reader;
try
{
reader = methodThatReturnsAReader();
}
catch(Exception ex)
{
// handle the exception
}
finally
{
// close the reader
reader.Dispose();
}
More Information
MSDN - IDisposable Interface
MSDN - SqlDataReader Class
As long as you're sure that dr.Close() is being called every time (even in the case of an exception being thrown), then yes your connections will also close. However, it's generally good practice to wrap that type of code into a try/finally block, where the finally block contains the dr.Close() statement.
The other alternative is a using statement, which takes advantage of the IDisposable interface implemented by SqlDataReader.
I'd recommend you to never return a DataReader from a method. You give the responsibility of closing the DataReader to the method caller. If the method caller doesn't assure that the DataReader is closed, even if an exception happens, you'll be in serious trouble.
Definitely, you should not do it this way.
What is worst, on some circumstances, an open DataReader can create locks in the database.
The only exception would be if the method is private, and you assure that all of the methods callers are closing the DataReader. But it's still quite error-prone.
The using statement, wrapped around SqlDataReader dr = GetMoreData() will protect you, as long as it's used in every place where GetMoreData() is called. That's hard to manage, so you can better protect yourself by changing the design.
From Microsoft Patterns and Practices:
"Use a DataSet when the following conditions are true:
-You have to cache or pass the data between layers."
compared with:
"Use a DataReader when the following conditions are true:
-you have a data container such as a business component that you can put the data in."
I would say your application has layers and doesn't appear to use business components. While it's true that DataSets have a much larger overhead than DataReaders, consider this:
cost of leaked connections (high, unpredictable) vs cost of using DataSets (measurable)
how much data do you need - can you return DataTable or DataRow instead of a DataSet?
DataReaders are great for low level code, such as Data Access components, but should not be passed around between different parts of your application.
So, I'm getting the error as per my title line. Seems pretty self- explanatory, but my understanding is that objects within the "using" block are disposed of? This error appeared after another minor bug interrupted code execution, so perhaps I'm stuck with an open reader that I need to close or shut down? Any help would be appreciated?
public override long GetStatsBenchmark(String TableName)
{
using (SqlCommand cmd = new SqlCommand("sprocReturnDataPointBenchmark", this.sqlConnection))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlParameter outputParameter = new SqlParameter
{
ParameterName = "#benchmark",
Direction = System.Data.ParameterDirection.Output,
SqlDbType = System.Data.SqlDbType.BigInt,
};
cmd.Parameters.Add(outputParameter);
SqlParameter inputParameter = new SqlParameter
{
ParameterName = "#tblName",
Direction = System.Data.ParameterDirection.Input,
SqlDbType = System.Data.SqlDbType.NVarChar,
Value = TableName
};
cmd.Parameters.Add(inputParameter);
cmd.ExecuteNonQuery();
return (long)outputParameter.Value;
}
}
I do not think that the code you have shown is the cause of the problem. While it is good practice to dispose of SqlCommand (IDbCommand) objects, in practice I have not found it to be necessary. What is necessary is to dispose of SqlDataReader (IDataReader) objects after you have finished using them. As the error message suggests, look for a usage of an SqlDataReader object in your code that is not being disposed. The exception may be thrown from the code you are displaying, but I would suspect that the cause is because of an SqlDataReader associated with the same SqlConnection used earlier in the program execution that has not been disposed.
An issue with the using clause is that it does not provide a way to process exceptions in the implicit try/finally block that the compiler generates for you.
You can
1) wrap your using clause with a try/catch, or
2) manually code a try/catch/finally instead of using, calling Dispose in the finally block and adding exception handling in a catch block.
There are slight drawbacks to either technique, but either will work
You can add MARS (multiple active result sets) to your connection string, to allow multiple recordset (or similar) open at the same time.
Add
MultipleActiveResultSets=true;
or
MARS Connection=True;
to your connection string (http://www.connectionstrings.com/sql-server-2008) and this will allow multiple handles, but if the previous operation has been "interrupted" in an exception, try avoid using "USING" or use a try/catch inside it.