Using on an object created in a different method - c#

I'm trying to make a generic SQL call, which led me to an interesting question. I have a method that executes the SQL, and returns a SQLDataReader.
private SqlDataReader ExecuteSql(SqlCommand command)
{
using (var connection = new SqlConnection(ConnectionText, Credentials))
{
command.Connection = connection;
connection.Open();
return command.ExecuteReader();
}
}
The calling command takes the reader and processes the returned data correctly. However, knowing that the reader needs to be disposed of, I enclosed it in a using statement.
using (SqlDataReader reader = ExecuteSql(command))
{
while (reader.Read())
{
try { ... }
catch(Exception e) { ... }
}
}
I think Dispose should be called on the SqlDataReader at the end of the using statement despite where in the code it was created. However, I have not been able to find anything that specifically confirms this.
Generalizing, can the using statement be successfully used on an object that was created elsewhere in the code?
As a side note, I do realize that if the SqlDataReader was created as an object in the ExecuteSql method rather than returned directly, then there could be an issue with it throwing an exception while in the ExecuteSql method and not being disposed of.

You can accomplish this by passing an Action like so:
private void ExecuteSql(SqlCommand command, Action<SqlDataReader> action)
{
using (var connection = new SqlConnection(ConnectionText, Credentials))
{
command.Connection = connection;
connection.Open();
using (var reader = command.ExecuteReader())
{
action(reader);
}
}
}
Then the calling function:
var myCommand = //...
int id;
ExecuteSql(myCommand, (reader) => {
id = reader.GetInt32(0);
});
Now any caller doesn't need to know if they have to dispose of it or not and your connection will be disposed after the method has done it work on the reader.

It's OK to use the object created in another method in the using statement.
However, in your case, you are using an SqlDataReader which uses the SqlConnection which is disposed at the end of the ExecuteSql call.
As explained here, you need a valid connection object to use the SqlDataReader

Related

Encapsulating and Disposing SqlClient Objects In Order

I am trying to layer my Sql client object calls such that they get disposed of reliably. Something like this:
Open database connection -> Create command -> Read results -> close
command -> close database connection
So far this has succeeded when I do all of these things in the same method.
The problem is this is error prone. And a mess to read through.
When I try to create a common method to handle this that cleans up everything and returns a reader the connection gets closed before the reader starts.
//closes connection before it can be read...apparently the reader doesn't actually have any data at that point ... relocating to disposable class that closes on dispose
public SqlDataReader RunQuery(SqlCommand command)
{
SqlDataReader reader = null;
using (var dbConnection = new SqlConnection(_dbConnectionString))
{
try
{
dbConnection.Open();
command.Connection = dbConnection;
reader = command.ExecuteReader(); // connection closed before data can be read by the calling method
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
dbConnection.Close();
}
}
return reader;
}
I can get around this by creating my own class that implements IDispose (etc) but then when I wrap it with the same using statement it takes up just as many lines as a database connection using statement.
How can I take care of the data base connection in a repeatable class that takes care of all these artifacts and closes the connection?
You could create a class that holds an open database connection that is reusable, but I suggest reading the data into a list and returning the result:
public List<object> RunQuery(SqlCommand command)
{
List<object> results = new List<object>();
using (var dbConnection = new SqlConnection(_dbConnectionString))
{
try
{
dbConnection.Open();
command.Connection = dbConnection;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
// Repeat for however many columns you have
results.Add(reader.GetString(0));
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
return results;
}
I don't know the structure of your data, but the important point is that you need to read your data (reader.GetString does this) before you dispose of the connection. You can find more information on how to properly read your data here.
Edit: As mentioned, I removed your finally statement. This is because your using statement is essentially doing the same thing. You can think of a using statement as a try-finally block. Your disposable object will always be disposed after the using statement is exited.
so there's no way to make a reusable method that tucks away all/most of the nested using statements?
There is a specific pattern supported for returning a DataReader from a method, like this:
static IDataReader GetData(string connectionString, string query)
{
var con = new SqlConnection(connectionString);
con.Open();
var cmd = con.CreateCommand();
cmd.CommandText = query;
var rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
return rdr;
}
Then you can call this method in a using block:
using (var rdr = GetData(constr, sql))
{
while (rdr.Read())
{
//process rows
}
} // <- the DataReader _and_ the connection will be closed here

Do I need to close and dispose the SQLConnection explicitly?

SqlDataReader rdr = null;
con = new SqlConnection(objUtilityDAL.ConnectionString);
using (SqlCommand cmd = con.CreateCommand())
{
try
{
if (con.State != ConnectionState.Open)
con.Open();
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(Parameter);
cmd.CommandText = _query;
rdr = cmd.ExecuteReader();
}
catch (Exception ex)
{
throw ex;
}
}
In this above code, sqlconnection is opened inside the managed code. Hence, will the connection object be disposed automatically upon ending the scope of USING?
You have to care about the disposal of SqlConnection, since it's a disposable object. You can try this:
using(var sqlConnection = new SqlConnection(objUtilityDAL.ConnectionString))
{
using (SqlCommand cmd = con.CreateCommand())
{
// the rest of your code - just replace con with sqlConnection
}
}
I suggest you replace the con with a local variable - if there isn't already (it does not evident from the code you have posted). There is no need for using a class field for this purpose. Just create a local variable, it would be far more clear to track it.
You should Dispose every temporary IDisposable instance you create manually, i.e. wrap them into using:
// Connecton is IDisposable; we create it
// 1. manually - new ...
// 2. for temporary usage (just for the query)
using (SqlConnection con = new SqlConnection(objUtilityDAL.ConnectionString)) {
// Check is redundant here: new instance will be closed
con.Open();
// Command is IDisposable
using (SqlCommand cmd = con.CreateCommand()) {
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(Parameter);
cmd.CommandText = _query;
// Finally, Reader - yes - is IDisposable
using (SqlDataReader rdr = cmd.ExecuteReader()) {
// while (rdr.Read()) {...}
}
}
}
Please, notice that
try {
...
}
catch (Exception ex) {
throw ex;
}
is at least redundant (it does nothing but rethrow the exception, while loosing stack trace) and that's why can be dropped out
In general:
In the .Net framework, nothing gets disposed automatically. Otherwise we wouldn't need the IDisposable interface. The garbage collector can only handle managed resources, so every unmanaged resource must be handled in code in the dispose method.
So as a rule, every instance of every class that is implementing the IDisposable must be disposed either explicitly by calling it's Dispose method or implicitly with the using statement.
As best practice, you should strive to use anything that implements the IDisposable interface as a local variable inside a using statment:
using(var whatever = new SomeIDisposableImplementation())
{
// use the whatever variable here
}
The using statement is syntactic sugar. the compiler translates it to something like this:
var whatever = new SomeIDisposableImplementation();
try
{
// use the whatever variable here
}
finally
{
((IDisposable)whatever).Dispose();
}
Since the finally block as guaranteed to run regardless of whatever happens in the try block, your IDisposable instance is guaranteed to be properly disposed.
With SqlConnection specifically, in order to return the connection object back to the connection pool, you must dispose it when done (the Dispose method will also close the connection, so you don't need to explicitly close it) - So the correct use of SqlConnection is always as a local variable inside the using statement:
using(var con = new SqlConnection(connectionString))
{
// do stuff with con here
}

Database Connection from another class

I have created a class in my program to handle database connection. This class includes a method named OpenConnection() to open the connection to the database. I'm not convinced that my program meets the standard of clean code. Here is the method.
public void OpenConnection()
{
if(connection==null || connection.State != Connection.Open)
{
connection = new OracleConnection(this.connectionString);
connection.Open();
}
}
This method works okay but I just want to make sure if this is a safe way and I am not exploiting my program in any way. Thank You in advance
Update
I also added the following methods in the class to close the connection and dispose it.
public void CloseConnection()
{
if (dbconnect != null | dbconnect.State != ConnectionState.Closed)
{
dbconnect.Close();
}
}
//Here the IDsiposable method is implemented
public void Dispose()
{
CloseConnection();
}
You can use using clause and it's going to handle the Dispose automatically.
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command = new SqlCommand("UpdateEmployeeTable", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#EmployeeID", 123));
command.CommandTimeout = 5;
command.ExecuteNonQuery();
connection.close();
}
Your solution as coded seems ok if you add the cases suggested in this answer and if it's meant to be used on a single thread and within a very limited scope. That said it appears like you are gearing up to use this class as a parameter across many method calls because you want to
mix business logic and persistence concerns
or share an instance in such a way that other methods don't have to be concerned about whether to open the connection (e.g. a higher call in the call stack has not yet called Open) or not (e.g. a prior call in the call stack did open the connection (what we'd call an "ambient" connection)).
Either of these strategies usually leads to trouble. It's better to keep the scope small, where you know the connection is open and when to close it:
using (var connection = new OracleConnection(...))
{
connection.Open();
...
}
When you have this small scope, your abstraction now provides no value.
You have a possible resource leak owing to the fact that OracleConnection implements IDisposable. Also, calling close on a connection in ConnectionState.Executing or Fetching could be bad as it will rollback all uncommitted transactions.
public void OpenConnection()
{
if (connection == null)
{
connection = new OracleConnection(this.connectionString);
connection.Open();
return;
}
switch (connection.State)
{
case ConnectionState.Closed:
case ConnectionState.Broken:
connection.Close();
connection.Dispose();
connection = new OracleConnection(this.connectionString);
connection.Open();
return;
}
}

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.

C# SqlDataReader close method

Which of these methods is better for closing SqlDataReader:
SqlDataReader reader = comm.ExecuteReader();
while (reader.Read())
{
}
reader.Close();
reader.Dispose();
or
SqlDataReader reader = comm.ExecuteReader(CommandBehavior.CloseConnection);
while (reader.Read())
{
}
or there are another further closing methods?
The correct way of handling this is the using statement:
using(SqlDataReader reader = comm.ExecuteReader(CommandBehavior.CloseConnection)) {
while (reader.Read())
{
}
}
This way the object gets disposed correctly (and you don't need to call Close()).
A using statement is the best practice in such situations from my experience. It makes sure the connection is properly closed even if an exception happens somewhere inside.
using (SqlDataReader reader = comm.ExecuteReader())
{
while (reader.Read())
{
//Do stuff...
}
}
Of course you could do the same with a try { } finally { }, which is what the using statement does internally. I found it's generally a good idea to get in the habit of always handling readers via the using statement to avoid the possibility of leaked connections.
Use first scenario if you work with reader within one method and second one if you pass reader as return value (not within one scope).
the doc you need is this one: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.close.aspx
To quote: "You must explicitly call the Close method when you are through using the SqlDataReader to use the associated SqlConnection for any other purpose."

Categories