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.
Related
I got this code:
try
{
using (OracleConnection c = new OracleConnection(globalDict[byAlias(connAlias)].connString))
{
c.Open();
using (OracleCommand recordExistentQuery = new OracleCommand("regular.IsExistent", c))
{
// here working on oraclecommand
}
}
} catch(Exception exc) { }
OracleConnection is class of devArt dotConnect for Oracle.
Will this code call c.Close() when it goes out of (OracleConnection c = new OracleConnection(globalDict[byAlias(connAlias)].connString)) { .... } ?
No, it will call Dipose(). A using block will implicitly call Dispose() on the object specified in the using statement.
But often times for a database connection, Dispose() handles the Close() functionality, releasing the connection/processId that keeps a connection.
I would also like to add that in the event of an exception somewhere in your //here working on oraclecommand (basically inside your using(...){ } statement, Dispose() will also be called.
By design, you should be able to make multiple to calls to an object implementing IDisposable. In your case, issuing a calling a call to Close() after your using block of code will simply do nothing, as the connection has already closed/been returned to the pool. Any additional calls after the object has cleaned up should just return and do nothing.
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.
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.
If I use "using" construct, I know that the object gets automatically disposed. What happens if a statement inside an "using" construct raises an exception. Is the "using" object still disposed? If so, when?
A using block is converted - by the compiler - to this:
DisposableType yourObj = new DisposableType();
try
{
//contents of using block
}
finally
{
((IDisposable)yourObj).Dispose();
}
By putting the Dispose() call in the finally block, it ensures Dispose is always called - unless of course the exception occurs at the instantiation site, since that happens outside the try.
It is important to remember that using is not a special kind of operator or construct - it's just something the compiler replaces with something else that's slightly more obtuse.
This article explains it nicely.
Internally, this bad boy generates a try / finally around the object being allocated and calls Dispose() for you. It saves you the hassle of manually creating the try / finally block and calling Dispose().
Actually Using block is Equivalent to try - finally block, Which ensures that finally will always execute e.g.
using (SqlConnection con = new SqlConnection(ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("Command", con))
{
con.Open();
cmd.ExecuteNonQuery();
}
}
Equals to
SqlConnection con = null;
SqlCommand cmd = null;
try
{
con = new SqlConnection(ConnectionString);
cmd = new SqlCommand("Command", con);
con.Open();
cmd.ExecuteNonQuery();
}
finally
{
if (null != cmd);
cmd.Dispose();
if (null != con)
con.Dispose();
}
I know I asked a related question earlier. I just had another thought.
using (SqlConnection conn = new SqlConnection('blah blah'))
{
using(SqlCommand cmd = new SqlCommand(sqlStatement, conn))
{
conn.open();
// *** do I need to put this in using as well? ***
SqlDataReader dr = cmd.ExecuteReader()
{
While(dr.Read())
{
//read here
}
}
}
}
The argument is that: Since the SqlDataReader dr object is NOT A NEW OBJECT LIKE THE connection or command objects, its simply a reference pointing to the cmd.ExecuteReader() method, do I need to put the reader inside a using. (Now based on my previous post, it is my understanding that any object that uses IDisposable needs to be put in a using, and SQLDataReader inherits from IDisposable, so I need to put it. Am I correct in my judgement?) I am just confused since its not a new object, would it cause any problems in disposing an object that simply is a reference pointer to the command?
Many thanks
I think you are mistaken. The dr is a reference to the object returned by cmd.ExecuteReader, which is going to be a new object. In your example, nothing will dispose dr, so yes it needs to be in a using, or manually disposed.
Your judgement about IDisposable implementors needing to be in a using is not correct. They will function fine outside. A using statement is just syntactic sugar for a try ... finally. Things implementing IDisposable should have Dispose called, because they are signalling that they need to dispose certain state in a deterministic way.
Note that if you do not call Dispose, its not always a problem. Some objects also implement the finalizer, which will be triggered by the garbage collector. If they do not implement the finalizer, they might leave unmanaged memory unreclaimed. This will remain unreclaimed until your application closes. All managed memory is eventually reclaimed, unless it is not elligible for garbage collection.
Re-written:
using (SqlConnection conn = new SqlConnection('blah blah'))
using(SqlCommand cmd = new SqlCommand(sqlStatement, conn))
{
conn.open();
using (SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
//read here
}
}
}
You should wrap the data reader in a using statement as the ExecuteReader method is creating a new data reader instance that should also be disposed of.