Ive been doing some research today on when an how to use the "using" statement to dispose of my sql objects.
However I'm still confused about when and how to catch unforseen errors. I have a simple method here and would appreciate any input on wheter its correct or I'm doing something wrong?
private BindingList<My_Object> Search(int ID)
{
string strSelectStatement =
"SELECT 'coloumns' " +
"FROM 'table' " +
"WHERE ID = #ID;";
DataTable dt = new DataTable();
try
{
using (SqlConnection sqlConn = new SqlConnection(m_SQLConnectionString))
{
using (SqlCommand cmd = new SqlCommand(strSelectStatement, sqlConn))
{
cmd.Parameters.Add("#ID", SqlDbType.Int).Value = ID;
using (SqlDataAdapter adpt = new SqlDataAdapter(cmd))
{
adpt.Fill(dt);
}
}
}
My_Object myObject;
BindingList<My_Object> myObjectList = new BindingList<My_Object>();
foreach (DataRow row in dt.Rows)
{
myObject = new My_Object();
//Fill/set myObject properties and add to myObject list
}
return myObjectList;
}
catch (Exception)
{
//throw the the exception with its stack trace up to the main call
throw;
}
}
So what my catch here would do is catch an error if anything went wrong when running adapter.Fill, or while building myObject/list for example.
Thanks
In C# . The using statement defines the scope of an item to be disposed. This can be called for any object which implements the IDisposable interface.
http://msdn.microsoft.com/en-us/library/system.idisposable.aspx
So if you had to not use using blocks you would call the dispose method on the class to release/clean up resources created by the object.
When calling a class that implements the IDisposable interface, the try/finally pattern make sure that unmanaged resources are disposed of even if an exception interrupts your application.
If an exception is thrown in the case of a using statement the dispose will still be called. You can also stack using statements
using (SqlConnection sqlConn = new SqlConnection(m_SQLConnectionString))
using (SqlCommand cmd = new SqlCommand(strSelectStatement, sqlConn))
{
cmd.Parameters.Add("#ID", SqlDbType.Int).Value = ID;
using (SqlDataAdapter adpt = new SqlDataAdapter(cmd))
{
adpt.Fill(dt);
}
}
with regards to exception handling. It is not wise to catch all exceptions try to catch the specific exceptions thrown by the class or method. You can view exception details on msdn so SQLConnection : http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.open.aspx
InvalidOperationException
Cannot open a connection without specifying a data source or server.
or
The connection is already open.
SqlException
A connection-level error occurred while opening the connection. If the Number property contains the value 18487 or 18488, this indicates that the specified password has expired or must be reset. See the ChangePassword method for more information.
So these are the exceptions you should cater for. Hope that helps!
Don't catch 'unforeseen' errors, since there's nothing you can do if truly unforeseen.
Unless of course you are wishing to handle these errors in some way, say, to log messages - but the system does that for you - then they are no longer 'unforeseen', since you're expecting them.
As for the code posted, there are problems. Firstly, the try / catch could be said to be trying too much, and given that you have usings in there, that is pointless (if exceptions aren't going to be handled.) It also catches a generic exception, which is highly discouraged; catches should be formulated to filter those that you can handle, and in appropriate order. To catch just to throw is also pointless.
Don't catch exceptions if you can do nothing about it. If you catch them is in order to clean up the unmanaged ressources or for logging purposes.
You might have a look on MSDN "Best Practices for Handling Exceptions" http://msdn.microsoft.com/en-us/library/seyhszts.aspx
You don't need the try..catch {throw}. This is the same as not having a try..catch block at all.
If you want to log the error of display a friendly message, then put the code in the catch { }.
The Dispose will still be called on the SqlConnection, even if the code crashes.
You can catch multiple exceptions at the end of your try statement. This means you can catch each different type of error that could occur i.e. InvalidOperationException / SqlException. MSDN Explains here:
http://msdn.microsoft.com/en-us/library/ms173162(v=vs.80).aspx
Since you have enclosed your whole code in try/Catch it will catch all errors raised within try/catch code block.
But don't follow this apprach only catch those errors specifically which you want to handle or log.
this is recommended because catching error is an overhead.
Related
I have a method that returns a List. Now I want to know how to place the try/catch blocks properly. If I place the return statement inside try I get error
Not all code paths return a value
If I place after catch(like I'm doing currently) it will return the products even after an Exception. So what should be the best way?
Here is the method:
public List<Product> GetProductDetails(int productKey)
{
List<Product> products = new List<Product>();
try
{
using (SqlConnection con = new SqlConnection(_connectionString))
{
SqlCommand cmd = new SqlCommand("usp_Get_ProductDescription", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#riProductID", productKey);
con.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Product product = new Product(reader["Name"].ToString(), reader["Code"].ToString());
products.Add(product);
}
}
}
}
catch { }
return products;
}
Remove the complete Try and Catch blocks. Apparently you are unable to handle the exceptions in the GetProductDetails method so just let them be thrown.
However the calling code can make the decision:
IList<Product> products = null;
try
{
products = GetProductDetails(3);
}
catch(Exception ex)
{
// Here you can make the decision whether you accept an empty list in case of retrieval errors.
// It is the concern of this method, not of the ProductDetails method.
// TODO: Use logging
products = new List<Product>();
}
I can imagine it feels like code duplication if you have to write this in every method using the GetProductDetails method. However consider, when you have X implementations, you want to react differently to not being able to get product details. You will have to come up with workarounds. You might even end up with weird bugs which are hard to troubleshoot.
That depends on what should happen in an exceptional case. If this might happen for some reason which isnĀ“t "bad enough" to let the app crash or if you are able to handle that exception appropriately then you might go with your current appraoch - however you should definitly leave at least a log-message within the catch-clause that contains the error which has been thrown:
catch (Exception e)
{
log.Info(e.Message);
}
This way you get all results within your list except those that caused any exceptions. You can simply continue work with all the results that you got and ignore those errorous (supposing you logged them in any way).
If it is a really unexpected behaviour (which is the intended one for exceptions, this is why they are called exceptions) you should delete all this try/catch from within your method and handle any exceptions outside the method as Maurice already mentioned.
At the moment, you don't return anything if an exception is thrown.
Use try, catch, finally. (May you want to see the MSDN page for more official information)
try
{
//try to execute this code
}
catch
{
//execute this if an exception is thrown
}
finally
{
//execute this code, after try/catch
}
So if you place your return statement into the finally section, you will return your list even if there's an exception thrown...
I found that my codebase contains various data access code where I have used using statements in two different ways. Which is the better way if any and are these two methods different? Any problems that could arise from not instantiating the SqlConnection and SqlCommand in the using statement? Ignore the obvious inconsistency problem.
Method 1:
public int SampleScalar(string query, CommandType queryType, SqlParameter[] parameters)
{
int returnValue = 0;
SqlConnection objConn = new SqlConnection(ConnString);
SqlCommand objCmd = new SqlCommand(query, objConn);
objCmd.CommandType = queryType;
if (parameters.Length > 0)
objCmd.Parameters.AddRange(parameters);
using (objConn)
{
using (objCmd)
{
objConn.Open();
try
{
returnValue = (int)objCmd.ExecuteScalar();
}
catch (SqlException e)
{
Errors.handleSqlException(e, objCmd);
throw;
}
}
}
return returnValue;
}
Method 2:
public int SampleScalar2(string query, CommandType queryType, SqlParameter[] parameters)
{
int returnValue = 0;
using (SqlConnection objConn = new SqlConnection(ConnString))
{
using (SqlCommand objCmd = new SqlCommand(query, objConn))
{
objConn.Open();
objCmd.CommandType = queryType;
if (parameters.Length > 0)
objCmd.Parameters.AddRange(parameters);
try
{
returnValue = (int)objCmd.ExecuteScalar();
}
catch (SqlException e)
{
Errors.handleSqlException(e, objCmd);
throw;
}
}
}
return returnValue;
}
In the first snippet, if there are any exceptions that occur after the IDisposable object is created and before the start of the using, then it won't be properly disposed. With the second implementation, there is no such gap that could result in unreleased resources.
Another problem that can occur with the first approach is that you could use an object after it has been disposed, which is not likely to end well.
It's possible that you are ensuring no exception could possibly occur, and maybe you're not. In general, I would never use the first method simply because I don't trust myself (or anyone else) to never ever ever make a mistake in that unprotected space. If nothing else, I'll need to spend time and effort looking very closely to be sure that nothing can ever go wrong. You don't really gain anything from using that less-safe method either.
I always go with the second method. It's easier to read and understand what objects are being disposed of at the end of a given block. It will also prevent you from using an object that has been disposed.
If you not use using you don't dispose your objets no managed, and GC no dispose
GC dispose only objects managed and sql connection is not managed so you must dispose, using use dispose in the end
Second one is better. Please read http://msdn.microsoft.com/en-us/library/yh598w02.aspx last remark.
In first object stays in scope after it's disposal. Using it then is not good practice.
Per MSDN
You can instantiate the resource object and then pass the variable to the using statement, but this is not a best practice. In this case, the object remains in scope after control leaves the using block even though it will probably no longer have access to its unmanaged resources. In other words, it will no longer be fully initialized. If you try to use the object outside the using block, you risk causing an exception to be thrown. For this reason, it is generally better to instantiate the object in the using statement and limit its scope to the using block.
I am working on a generic class and am working on handling errors. I am using a try catch on one spot where I am getting an error. The question is, how do I return that error back to the calling method?
public static DataTable GetData(string connString, string sqlStatement, Action<iDB2ParameterCollection> parameters)
{
DataTable dt = new DataTable();
using (iDB2Connection conn = new iDB2Connection(connString))
{
using (iDB2Command cmd = new iDB2Command(sqlStatement, conn))
{
conn.Open();
if (parameters != null) { parameters(cmd.Parameters); }
try
{
using (iDB2DataAdapter da = new iDB2DataAdapter(cmd)) { da.Fill(dt); }
}
catch (iDB2SQLErrorException e)
{
}
conn.Close();
}
}
return dt;
}
By not catching it in a base class!
I am not a fan of capturing and swallowing exceptions at the base class level.
Let your derived classes worry about these details.
Side Note (Evidence of position):
You'll notice that in practically any API, the doucmentation will report what exceptions will be thrown with classes. If they were to catch them in a base class, they have effectively swallowed them rendering you helpless as the user of said classes.
Additional Articles:
...instead of writing our abstractions based on details, the we should
write the details based on abstractions.
This is a core tenant of Dependency Inversion Principle.
Take a look at this article for some really good things to consider in your design process, http://www.oodesign.com/design-principles.html
We do this, for the same reason you appear to be doing it. So that you can ensure the connection is closed.
We just re-throw the same error and lose the connection in the "finally" block. This lets the connection be closed and still bubble the connection back up to the caller, because the "finally" block gets executed regardless.
catch (iDB2SQLErrorException e)
{
throw e;
}
finally
{
cn.Close();
}
The above code is what we've used for years, but thanks to the comments, I think it might need tweaking. See this blog post for info on how to preserve the stack trace with exception handling: http://weblogs.asp.net/fmarguerie/archive/2008/01/02/rethrowing-exceptions-and-preserving-the-full-call-stack-trace.aspx
You could implement some logic to handle to exception internally in this method and re-throw it again. The exception will bubble up in the call stack;
Other option is to use error codes to pass the error up in the stack. It depends on the API.
Either don't catch it and let the caller handle it, or throw your own error that wraps the original one:
class DataRetrievalException : Exception {
DataRetrievalException(String message, Exception cause) : base(message, cause) {}
}
// ...
catch (iDB2SQLErrorException e) {
throw new DataRetrievalException("Error retrieving data from database", e);
}
As it is, I tried error-proofing my code and ended up making it look quite messy.
I have a function set up to read a certain type of file. I want the function to return false if there was a problem, or true if everything worked. I'm having trouble figuring out how to structure everything.
I have an initial try-catch block that tries to open a file stream. After that though, I have certain other checks I make during the reading process such as file size and values at certain offsets. The way I set it up was with if else statements. Such as:
if(condition){
}
else{
MessageBox.Show("There was an error");
br.Dispose();
fs.Dispose();
return false;
}
...br being the binary reader and fs the filestream. There are many blocks like this, and it seems like bad practice to write the same thing so many times. The first thing that comes to mind is to wrap the entire thing in a try-catch statement and throw exceptions instead of using the if else blocks. I remember when reading about try-catch statements that it's good to have them, but not to wrap everything with them. To be honest, I still don't completely understand why it would be bad practice to wrap everything in try catch statements, as they only have an effect when there's an error, in which case the program is going south anyway...
Also, do I have to close the binary reader and file stream, or will closing one close the other? Is there any way to use them without having to dispose of them?
How about making use of the using keyword? this wraps your use of an IDisposable in a try - finally block;
bool success = true;
using(var fs = new FileStream(fileName, FileMode.Create)))
using(var br = new BinaryReader(fs))
{
// do something
success = result;
}
return success;
The nested using blocks will ensure that both the filestream and binary reader are always properly closed and disposed.
You can read more about using in MSDN. It makes the use of IDisposable a little neater, removing the need for explicit excpetion handling.
Regarding your statement:
I remember when reading about try-catch statements that it's good to
have them, but not to wrap everything with them.
I always use the simple rule that if I cannot handle and recover from an exception within a particular block of code, don't try to catch it. Allow the exception to 'bubble up' the stack to a point where it makes more sense to catch it. With this approach you will find that you do not need to add many try-catch blocks, you will tend to use them at the point of integration with services (such as filesystem, network etc ...) but your business logic is almost always free of exception handling mechanisms.
Just use the using keyword for your disposable objects. Within the block of the using keyword you can throw exceptions or return without having to worry about disposal; it will happen automagically for you.
try-catch blocks are not a very good idea only because there exists a much better alternative: the try-finally blocks. But the using keyword is even better because it essentially expands into a try-finally block and it takes care of object disposal.
Closing the file stream will also close the binary reader, and so will disposing of them do. Why do you want to use them without disposing them? Disposing them is better, and disposing them via using is the best thing to do.
I think the best way to make sure filestreams are disposed is to wrap their usage with the following using block
using (FileStream)
{
....
}
Yes, it is bad practice.
Instead of returning booleans that indicate whether a problem occurred or not, you should throw exceptions. Example:
if (headNotValid)
throw new Exception("Header was not valid");
In some cases it may be advisable to make a new exception class.
When working with classes that inherit from IDisposable you should use the using directive.
using (var stream = new FileStream(filename))
{
}
That guarantees, that your stream is disposed, even if a exception is thrown within the using block.
In summary, I would prefer something like this:
private void string ParseFile(string filename)
{
using (var stream = new FileStream(filename))
{
if (somethingNotValid)
throw new Exception(...);
return ...;
}
}
And in your main:
{
try
{
var value = ParseFile(filename);
}
catch (Exception)
{
Console.WriteLine(..);
}
}
Use the using keyword. With using you can rewrite something like this:
public static int CountCars()
{
SqlConnection conn = new SqlConnection(connectionString);
try
{
SqlCommand cmd = conn.CreateCommand();
conn.Open();
try
{
cmd.CommandText = "SELECT COUNT(1) FROM Carsd";
return (int)cmd.ExecuteScalar();
}
finally
{
if(cmd != null)
cmd.Dispose();
}
}
finally
{
if(cmd != null)
conn.Dispose();
}
}
into this:
public static int CountCars()
{
using(SqlConnection conn = new SqlConnection(connectionString))
using(SqlCommand cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "SELECT COUNT(1) FROM Carsd";
return (int)cmd.ExecuteScalar();
}
}
Both code snippets will produce exactly the same IL code when compiled. The examples are from http://coding.abel.nu/2011/12/idisposable-and-using-in-c/ where I wrote some more details about using and IDisposable.
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.