Should I use a try/catch statement with the DataAdapter.Fill method? - c#

using (SqlConnection sqlConn = new SqlConnection(XYZ.Globals.ConnectionString))
{
using (SqlDataAdapter adapter = new SqlDataAdapter())
{
SqlCommand command = new SqlCommand("selCompanies", sqlConn)
{
CommandType = CommandType.StoredProcedure
};
command.Parameters.AddRange(searchParams.ToArray());
adapter.SelectCommand = command;
DataSet ds = new DataSet();
adapter.Fill(ds);
return ds;
}
}
Do I need to wrap the `adapter.fill()` in try catch finally block?

You only wrap things in a try/catch when you can handle whatever exceptions it throws. If you can't, there's no need to put it in a try/catch block.
The using statement is equivalent to a try/finally block.

The question would be what would I do differently if something went wrong. Typically, the correct action is to just let the exception raise upwards - after all, you weren't expecting an exception, so you can't do anything useful with it. The only subtlety here is IDisposable, where you actively want to clean things up as you go; so using statements for things like SqlConnection, SqlCommand, SqlDataReader etc are ideal (But that is try/finally, not try/catch). So the main change I would make tour code would be to dispose the command:
using (SqlDataAdapter adapter = new SqlDataAdapter())
using (SqlCommand command = new SqlCommand("selCompanies", sqlConn))
{
command.CommandType = CommandType.StoredProcedure;
//...snip...
}

That depends on whether this code is wrapped for exception handling at a higher level. At what scope do you want to handle errors in this logic - typically this would be for a given 'block' of logic, not for each function call. Handling DB errors is a good idea in general.
In any case, you do need to have another using on your SqlCommand or you will leak it.

The same applies this adapter.Fill() as to any other line of .net code:
If you have a good reason for catching and handling one particular exception, then catch it and handle it. If you don't have a good reason, don't catch it.
I don't see why this particular line should be error-handled in a specific way.

You only need to catch the exception from the fill here if you have error handling that will require the connection or command to be in scope.
Also, technically the adapter and the command will go out of scope as soon as you exit the using block for the connection. In many cases, this is probably sufficient to release those resources (the connection is the most valuable resource in most scenarios, since it creates overhead on the database server). It doesn't hurt to be explicit, though, especially if you're going to create multiple commands or adapters for the same conntection.

Related

when does dispose method is called in using block

I am trying to test this piece of code by putting in breakpoints. I want to make sure that after the using block the dispose method is called and the resources (SqlCommand), is gracefully released.
However nowhere in the using block I hit any dispose?
using (SqlCommand command = new SqlCommand(queryString, connection))
{
command.CommandType = CommandType.Text;
command.Parameters.Add("#OrganizationID", SqlDbType.Int);
command.Parameters["#OrganizationID"].Value = organizationId;
connection.Open();
SqlDataReader sqlDataReader = command.ExecuteReader(CommandBehavior.CloseConnection);
try
{
while (sqlDataReader.Read())
{
//do something
}
}
finally
{
sqlDataReader.Close();
}
}
The call to Dispose of IDisposable happens after the using block has finished execution, normally or abnormally (i.e. through an exception).
The only way you could catch the call in a source-level debugger is when you have the source code for your IDisposable - in your case it would be the source code of SqlCommand class.
One simple way of checking the way this works is to make your own IDisposable implementation, put it into a using block, and observe its behavior. The call to Dispose should follow immediately after completion of the using block.
The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler. The code example earlier expands to the following code at compile time (note the extra curly braces to create the limited scope for the object):
Key part is the "achieve the same result by putting the object inside a try block and calling finally".
SqlCommand command = new SqlCommand(queryString, connection);
try {
// your code here
} finally {
command.Dispose();
}
From MSDN

Code Analysis tool

I am using Visual Studio's code analysis tool, and one of the warnings it gives me is "Do not dispose objects multiple times: Object 'conn' can be disposed more than once in method 'CycleMessages.discernScan_Reprint()'. To avoid generating a System.OjectDisposedEx you should not call Dispose more than one time on an object. Line:61
private void discernScan_Reprint()
{
try
{
DataTable dt = new DataTable();
SqlConnection conn = new SqlConnection("my constring");
using (conn)
{
SqlCommand cmd = new SqlCommand("usp_myproc", conn);
cmd.CommandType = CommandType.StoredProcedure;
using(cmd)
{
cmd.Parameters.Add(new SqlParameter("#param", param));
conn.Open();
SqlDataReader dr = cmd.ExecuteReader();
dt.Load(dr);
conn.Close(); // this is line 61
}
}
switch(dt.Rows.Count)
{
default:
throw new Exception("message");
case 1:
//do Stuff
case 0:
//do stuff
break;
}
}
catch (Exception ex) {throw;}
}
I don't dispose the conn (explicitly via conn.Dispose();), I just close it and allow the using encapsulation to dipose of the conn object- I know I can allow it to be closed via the disposal, but why is it saying I'm disposing it twice? If anything it should warn me saying "You don't need to terminate connections on objects that will be disposed" or something like that. Am I missing something?
Edits:
From ref link on close...
The Close method rolls back any pending transactions. It then releases the connection to the connection pool, or closes the connection if connection pooling is disabled.
and
If the SqlConnection goes out of scope, it won't be closed. Therefore, you must explicitly close the connection by calling Close or Dispose. Close and Dispose are functionally equivalent. If the connection pooling value Pooling is set to true or yes, the underlying connection is returned back to the connection pool. On the other hand, if Pooling is set to false or no, the underlying connection to the server is closed.
I know that functionally Close() is the same as dispose, but that is not literal from my understanding. When I close the object it is not disposed. It is either closed or returned to the connection pool, disposing (again from my understanding) internally calls the close() methods- so while redundant, I still am baffled as to why it is explicitly saying it is already disposed, when it's not.
The Dispose pattern suggests that implementors provide synonyms for Dispose that make sense in the context of the object. One such synonym on SqlConnection is Close():
Close and Dispose are functionally equivalent.
Since you're explicitly calling Close(), and the object's Dispose() method is being called when the connection's using statement ends, you're effectively calling Dispose() twice.
The best approach is to just let the using block handle it for you, since it guarantees that Dispose() is called even when an exception occurs from inside the using block. It also sets the variable to null so that it can be GC'd as soon as possible.
Edits to respond to #alykin's questions
The documentation says that the Close() and Dispose() methods are functionally equivalent, but #alykin has identified a scenario where they don't actually do the same thing. If I'm reading her comment correctly, it works something like this:
The following works:
SqlConnection conn = GetConnSomehow();
SqlCommand cmd = conn.CreateCommand();
// ...
conn.Open();
cmd.ExecuteSomething();
cmd.Close();
// ... time passes ...
conn.Open();
The following doesn't:
SqlConnection conn = GetConnSomehow();
SqlCommand cmd = conn.CreateCommand();
using ( conn ) {
cmd.ExecuteSomething();
}
// ... time passes ...
// This won't compile, according to alykins.
conn.Open();
This shows that SqlConnection objects can be reused, at least when they've been only Close()'d.
Likely the reason why the second example with the using block doesn't compile is that the compiler knows that conn has been set to null when the using block ends, so it knows that you can't call methods on a null object reference.
I'm still not sure that this shows that a Dispose() is actually any different than a Close() though, since the incongruity arises due to the nulling semantic of the using block. It would be worthwhile testing whether or not an SqlConnection can be re-opened after it is Dispose()'d but not nulled. Even if it were, I wouldn't rely on that behavior since it is counter to Microsoft's own guidelines set in the Dispose Pattern documentation.
Additionally, I would not use the first block that doesn't use a using block - if an exception occurs, the connection may be leaked, or at least, held open for a non-deterministic amount of time until the GC sees that the object has been leaked and invokes its finalizer.
I would not rely on any difference in behavior between Close() and Dispose() - I would recommend against attempting to re-open a previously-closed SqlConnection object. Let the pooler handle actually keeping the connection alive even if you close or dispose the SqlConnection object you were handed.
A note on using statements.
Consider the following block of code:
IDisposable thing = GetThing();
using ( thing ) {
thing.DoWork();
}
That block of code is exactly identical to this block:
IDisposable thing = GetThing();
try {
thing.DoWork();
}
finally {
thing.Dispose();
thing = null;
}
And the following block, as considered by Microsoft, their documentation, and their analysis tools, counts as two disposes:
SqlConnection conn = GetConn();
using ( conn ) {
DoWork(conn);
conn.Close(); // code analysis tools count this as one Dispose().
} // implicit conn.Dispose() from the using block, so that's two.
Ignore the fact that Close and Dispose don't exactly do the same thing. They don't want you to rely on that, nor should you in case the behavior does actually get fixed.
It is informing you that the explicit close is disposing resources early. The using statement will automatically dispose it for you.
According to MSDN:
Close and Dispose are functionally equivalent.
Thus, calling .Close() disposes of the object. Additionally, since the object is in a using block, the compiler also calls .Dispose(). Only one of the two is needed. (And the latter is recommended in this case.)
Essentially, you just need to remove the call to Close() since the using block will handle that for you when it disposes of the object:
using (conn)
{
SqlCommand cmd = new SqlCommand("usp_myproc", conn);
cmd.CommandType = CommandType.StoredProcedure;
using(cmd)
{
cmd.Parameters.Add(new SqlParameter("#param", param));
conn.Open();
System.Data.SqlClient.SqlDataReader dr = cmd.ExecuteReader();
dt.Load(dr);
}
}
close(); and dispose(); essentially do the same thing, that is why you are receiving this warning. Check this link for more information.

SqlConnection.Close() inside using statement

I'm using this code:
public void InsertMember(Member member)
{
string INSERT = "INSERT INTO Members (Name, Surname, EntryDate) VALUES (#Name, #Surname, #EntryDate)";
using (sqlConnection = new SqlConnection(sqlConnectionString_WORK))
{
sqlConnection.Open();
using (SqlCommand sqlCommand = new SqlCommand(INSERT, sqlConnection))
{
sqlCommand.Parameters.Add("#Name", SqlDbType.VarChar).Value = member.Name;
sqlCommand.Parameters.Add("#Surname", SqlDbType.VarChar).Value = member.Surname;
sqlCommand.Parameters.Add("#EntryDate", SqlDbType.Date).Value = member.EntryDate;
sqlCommand.ExecuteNonQuery();
}
}
}
Is it wrong if I don't add sqlConnection.Close(); before disposing it? I mean. It's not showing any errors, no problems at all. Is it better to Close it first? If yes, why?
No need to Close or Dispose the using block will take care of that for you.
As stated from MSDN:
The following example creates a SqlConnection, opens it, displays some
of its properties. The connection is automatically closed at the end
of the using block.
private static void OpenSqlConnection(string connectionString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
Console.WriteLine("ServerVersion: {0}", connection.ServerVersion);
Console.WriteLine("State: {0}", connection.State);
}
}
The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler. MSDN
So ultimately your code line
using (sqlConnection = new SqlConnection(sqlConnectionString_WORK))
will be converted into a normal try finally block by compiler calling IDisposable object in the finally
According to MSDN documentation for the Close method:
you must explicitly close the connection by calling Close or Dispose. Close and Dispose are functionally equivalent.
Therefore, calling Dispose (implicitly so, even, using using) will cover your bases, as it were.
It's worth noting, too, I think,though not specific to your case, that Close will always effectively be called when the thing is wrapped in a using statement - which might not be the case should it be omitted and an exception occur without the proper try/catch/finally handling.
Is it wrong if I don't add sqlConnection.Close(); before disposing it
No, it is not as long as you are using your connection within Using. When you will leave the using scope, Dispose will be called for sql connection. which will close the existing connection and free-up all the resources as well.
The using statement is a try finally block and in your case the final block would have a connection.Dispose() call. So you don't really need a independent connection.Close() statement there.
The advantage is that this ensures the disposal even in case of an exception since the finally block will always run.
try
{
sqlConnection.Open();
// ....
}
finally
{
if(sqlConnection != null)
sqlConnection.Dispose();
}
You are using a Using which will Dispose() the object for you.
If you take the connection outside of the Using statement, then yes - you would need to close the connection when finished.
No, it is not wrong. The sqlConnection will close the connection after it will pass using block and call Dispose method. SqlConnection.Dispose() equal to SqlConnection.Close() method.
From MSDN: If the SqlConnection goes out of scope, it won't be closed. Therefore, you must explicitly close the connection by calling Close or Dispose. Close and Dispose are functionally equivalent.

Do I have to Dispose the SQLiteCommand objects?

How do I treat the SQLiteCommand object,
do I have to call Dispose() after ExecuteScalar, ExecuteNonQuery and ExecuteReader or not?
The documentation example on SQLiteCommand doesn't dispose it whilst
in the SQLiteTransaction the example disposes the SQLiteCommand object.
I always close the data reader object though. My application accesses the db from many threads.
Mostly I am interested in not leaking connections or disturbing SQLite. I am aware of using and IDisposable usage
It's best-practise to dispose everything that implements IDisposable as soon as you're finished with it because it might use unmanaged resources.
This should be done with the using-statement since it wraps the code that uses this object and because it disposes it also in case of an exception.
using(var con = new SQLiteConnection(conString))
using(var cmd = new SQLiteCommand(con))
{
con.Open();
// ...
} // also closes the connection
If it is disposable, dispose it if you will not use it again.
The best would be, to use using
using(SQLiteCommand cmd as new SQLiteCoammand())
{
...
}
So it will be disposed automatically when leaving the using scope.
Just do this:
using(var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString))
using(var command = connection.CreateCommand())
{
command.CommandText = "...";
connection.Open();
command.ExecuteNonQuery();
}
Not calling dispose on the command won't do anything too bad. However calling Dispose on it will supress the call to the finalizer, making calling dispose a performance enhancement.
The using statement will call Dispose on an object even if an exception occurs that bypasses the code that calls Close(). This way you don't have to write a try/finally block just to close the readers or the connection. You also avoid this 1-in-100 case where you forget to write the proper finally block.
Such 1-in-100 cases have a tendency to occur much more frequently than one would think

What's the right way to write my data access layer's methods?

Is this good enough ? do I need to add anything or remove anything ? like a rollback to my Sql Queries ? add catch() ? should my function accept only the property that I need or the object it self ? and how can I let the presentation layer know that the function's code was executed with no errors .. should I make it book instead of void or what ?
public static void DeleteAllCabinFeaturesFromACruise(int CruiseID)
{
string commandText = "DELETE FROM Cruise_Features WHERE CruiseID = #cruiseId";
SqlConnection connection = new SqlConnection(ConnectionString);
SqlCommand command = new SqlCommand(commandText, connection);
try
{
using (connection)
{
using (command)
{
command.Parameters.AddWithValue("#cruiseId", CruiseID);
connection.Open();
command.ExecuteScalar();
}
}
}
finally { connection.Close(); }
}
You are not using using correctly. The idea of using is to wrap some resource, that needs to be released in a safety-west, that protects it from exceptions. So, the correct way of using using (ha-ha) is the following:
using(SqlConnection connection = new SqlConnection(ConnectionString)){
{
using(SqlCommand command = new SqlCommand(commandText, connection)){
//your code here
}
}
The second issue is that you are executing your query as if it should return Scalar value. It's OK, but I think it's better use just Execute: command.Execute(); And, if you want some error handling, you'd better wrap
connection.Open();
command.ExecuteScalar();
in a try ... catch block like you have. Like this:
//I would place it inside inner-most using block, but nothing wrong placing it outside
try{
connection.open();
command.Parameters.AddWithValue("#cruiseId", CruiseID);
command.Execute();
}
//this catches ALL exceptions, regardless of source. Better narrow this down with
//some specific exception, like SQLException or something like that
catch (Exception e){
return false; //or whatever you need to do
}
You can remove the try...finally block. The "using" will take care of disposing the connection for you.
EDIT: As chibacity says, you should initialise the connection in the using to ensure correct disposal. Your error-handling (to prevent the users seeing the exception details) should be done in your UI layer, not your data-layer. It is entirely appropriate for a data-layer to throw exceptions.
string commandText = "DELETE FROM Cruise_Features WHERE CruiseID = #cruiseId";
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
SqlCommand command = new SqlCommand(commandText, connection);
// Your code.
}
For a simple query like that a rollback is probably not necessary - the query will either succeed or fail. For a more complicated query, a rollback would be necessary if you wanted to ensure that operations were atomic.
and how can I let the presentation layer know that the function's code was executed with no errors?
This really boils down to how you want to handle these cases in general. One rule of thumb is to ask yourself a question; are you expecting an error to occur significantly often, or not? So, for example, if the method should only fail if there was a communication error, then it's perfectly fine to throw an exception to the front-end. If, on the other hand, the delete operation can fall over because of various business rules that need to be validated (or, say, foreign key violations), then you should probably not throw those as exceptions. In the latter case, your method should return some information about success (simplistic version: a boolean, complex version: your own "OperationResult" class).
I'm simplifying things a lot here, but I believe these rules of thumb are valid.
EDIT: When I say "then it's perfectly fine to throw an exception to the front-end", I mean - throw it to the front end, but have the front-end handle it gracefully!
connection.Close() is redundant - using(connection) will dispose and close it.
Also, connection.Open() is usually placed in the beginning - to verify connection with the server .

Categories

Resources