If you employ a using clause to dispose of a connection, are other items within the clause that implement IDisposable also automatically disposed? If not, how do you handle making sure all IDisposable items are automatically disposed?
public static DataTable ReturnDataTable(
string ConnectionString, string CommandTextString, CommandType CommandType,
int CommandTimeout, List<System.Data.SqlClient.SqlParameter> ParameterList = null)
{
using (System.Data.SqlClient.SqlConnection Connection =
new System.Data.SqlClient.SqlConnection())
{
Connection.ConnectionString = ConnectionString;
System.Data.SqlClient.SqlCommand Command =
new System.Data.SqlClient.SqlCommand();
Command.Connection = Connection;
Command.CommandText = CommandTextString;
Command.CommandType = CommandType;
Command.CommandTimeout = CommandTimeout;
if (ParameterList != null)
{
if (ParameterList.Count > 0)
{
foreach (SqlParameter parameter in ParameterList)
{
Command.Parameters.AddWithValue(
parameter.ParameterName, parameter.Value);
}
}
}
System.Data.DataTable DataTable = new System.Data.DataTable();
System.Data.SqlClient.SqlDataAdapter DataAdapter =
new System.Data.SqlClient.SqlDataAdapter();
DataAdapter.SelectCommand = Command;
DataAdapter.Fill(DataTable);
return DataTable;
}
}
You can stack the statements like this (to initialize all disposable objects early on)
using (...)
using (...)
{
...
}
or you can use nested using statements for each disposable object you need
using (...)
{
using (...) { ... }
using (...) { ... }
}
Only an object created in the using clause will be disposed. If you want to make sure that call to dispose is automatically generated for every disposable object created inside of the using block you will need to wrap each of them in a using clause (or you can just call dispose or close, whichever they support, of course). So, the answer is not.
No. You will have to explicitly call Dispose on the ones that are not inside the parameters of the using statement.
Related
I've read various questions/suggestions about this exception. However what I am supposed to do in order to avoid it when I use retry policy? Connection might not end up closed and so parameters could not be reused?
public class ReliableSqlCommand
{
public List<ResultType> ExecuteReader<ResultType>() where ResultType : new()
{
var list = new List<ResultType>();
var retryPolicy = new DWSqlAzureExecutionStrategy(SqlMaxRetryCount, SqlMaxDelay);
retryPolicy.Execute(() =>
{
list = new List<ResultType>();
using (var sqlConnection = new SqlConnection(ConnectionString))
{
using (var sqlCommand = new SqlCommand(CommandText, sqlConnection))
{
sqlCommand.CommandTimeout = CommandTimeout;
sqlCommand.CommandType = CommandType;
sqlCommand.Parameters.AddRange(Parameters.ToArray());
sqlCommand.Connection = sqlConnection;
sqlConnection.Open();
using (SqlDataReader dataReader = sqlCommand.ExecuteReader())
{
while (dataReader.Read())
{
if (typeof(ResultType).BaseType == typeof(System.ValueType))
{
var sqlValue = dataReader.GetValue(0);
if (sqlValue == DBNull.Value)
list.Add(default);
else
list.Add((ResultType)ChangeType(sqlValue, typeof(ResultType)));
}
else
{
//handle complex types (objects)
ResultType item = new ResultType();
Type itemType = item.GetType();
for (int columnNr = 0; columnNr < dataReader.FieldCount; columnNr++)
{
PropertyInfo prop = itemType.GetProperty(dataReader.GetName(columnNr));
if (prop == null) continue;
var value = dataReader.GetValue(columnNr);
if (value == null || value == DBNull.Value)
{
prop.SetValue(item, null);
}
else
{
prop.SetValue(item, value);
}
}
list.Add(item);
}
}
sqlConnection.Close();
}
sqlCommand.Parameters.Clear();
}
}
});
return list;
}
}
ReliableSqlCommand contains this as a property:
public List<SqlParameter> Parameters { get; } = new List<SqlParameter>();
After reviewing your code, I could imagine the following. (Note that I haven't tested it.)
You pass a function to retryPolicy.Execute(), which seems to correctly handle your database actions, disposing all connections, commands, datareaders, etc.
However, I assume that the retryPolicy can already start executing a new run of that function while a previous run is still active/running (or at least not yet fully completed). In that case, the parameters in ReliableSqlCommand.Parameters will be added to a new instance of SqlCommand, which is clearly not allowed when those parameters are still "alive" in a previous running function call in the background (which is still waiting for a database timeout exception, perhaps).
I do not see a straightforward stable/reliable fix for this.
Within the function, you could try to make new copies/instances of the Parameter objects and assign those copies to the SqlCommand instance. But in case you have output parameters, you will have to update the ReliableSqlCommand.Parameters collection afterwards. When having multiple running/overlapping function calls, that might be tricky as well.
I think what you need to do is either to ensure the parameters are removed from the old command, or cache the command
If I understand correctly, the Execute function retries the lambda, and swallows any exceptions along the way. It does not execute multiple times concurrently.
Unfortunately, SqlCommand.Dispose does not remove the parameters from the command.
So option 1 is:
using (var sqlCommand = new SqlCommand(CommandText, sqlConnection))
{
try
{
.......
}
finally
{
sqlCommand.Parameters.Clear();
}
}
A better option in my opinion, given that a parameter is supposed to be used with only one command, is to cache the command also.
There is nothing wrong with this, as long as the connection is changed each time.
public ReliableSqlCommand
{
public SqlCommand Command { get; set; }
Then instead of using (var sqlCommand = new SqlCommand..., just use the existing _command:
_command.Connection = sqlConnection;
If you don't want to expose your command object directly, you could make a wrapper that adds and deletes the parameters.
It's not strictly necessary to dispose SqlCommand, because it's Dispose does nothing. But for consistency's sake, you may want to have ReliableSqlCommand be disposable as well.
This question already has answers here:
Does the using statement dispose only the first variable it create?
(6 answers)
Closed 9 years ago.
This may be answered elsewhere, but after doing a bit of searching I didn't find much on the subject outside of the normal using context.
I am curious if all objects created in a using block will be disposed of as well as the original object.
Here is the context:
Normally I would do something like this:
using (var conn = new SqlConnection(connectionString))
using (var cmd = new SqlCommand(commandText, conn))
{
//Do everything I need to here
}
I know that both conn and cmd go out of scope at this point and are disposed of because of the lovely using keyword.
I am curious if the same disposal rules would apply to the following statement:
using (var cmd = new (SqlCommand(commandText, new SqlConnection(ConnectionString)))
{
//Do everything I need here
}
Would the SqlConnection object that was created inline in the using statment be disposed of when cmd goes out of scope and is disposed of because it's associated with the object?
Also which would be syntactically preferred? I personally think the 2nd is cleaner, but I understand readability may come to play here as well.
For your second code, Dispose won't be called on SqlConnection instance when flow leaves using block unless SqlCommand.Dispose() do that internally (and no, it doesn't).
According to specification (8.13), using (ResourceType resource = expression) statement is transformed into:
{
ResourceType resource = expression;
try {
statement;
}
finally {
if(resource != null)
((IDisposable)resource).Dispose();
}
}
In your code, resource is SqlCommand, and that's the one Dispose is called on.
No.
using statements only apply to the resources declared directly in the statement; not to other allocations in the initializer.
You need a separate using statement for each resource.
According to MSDN, this code:
using (var temp = obj)
{
// ...
}
Translates to (including the extra curly braces to limit the scope):
{
var temp = obj;
try
{
// ...
}
finally
{
if (temp != null)
((IDisposable)temp).Dispose();
}
}
As you can see, if you substitute obj for new SqlCommand(commandText, new SqlConnection(ConnectionString)) then only the SqlCommand gets properly disposed.
{
SqlCommand temp = new SqlCommand(commandText,
new SqlConnection(ConnectionString));
try
{
// ...
}
finally
{
if (temp != null)
((IDisposable)temp).Dispose();
}
}
So, the SqlConnection won't get disposed unless the disposed SqlCommand does that. But it doesn't, and it shouldn't: it didn't create the object, therefore it must not destroy it either.
Certainly there are already answers that explains this correctly. This is covered by the specification as mentioned by others.
But you could just try it out. Here is an example:
static class Program
{
static void Main()
{
using (new DisposeMe("outer", new DisposeMe("inner", null)))
{
Console.WriteLine("inside using");
}
Console.WriteLine("after using scope");
}
}
class DisposeMe : IDisposable
{
public readonly string name;
public DisposeMe(string name, object dummy)
{
this.name = name;
}
public void Dispose()
{
Console.WriteLine("'Dispose' was called on instance named " + name);
}
}
Output:
inside using
'Dispose' was called on instance named outer
after using scope
(Of course if you nest two using statements, as in using (var inner = new DisposeMe("inner", null))
{
using (new DisposeMe("outer", inner))
{ ... } }, the Dispose method is called on both objects.)
I have two method “ExecuteNoQuery” (performs dbCommand.ExecuteNonQuery()) and “Query” performs (dbCommand.ExecuteReader()).
Both the methods are using same connection object. In ExecuteNoQuery method a lock is implemented(using connection object) and Query method implemented with out lock. In case of multiple thred, different thread accessing both the method simultaneously then what will happen?
Note: In Query method custom connection pooling is implemented with the same object.
public int ExecuteNoQuery(string sqlquery, Hashtable htData) {
try {
lock(Myservice.dbcon)
{
using (OracleCommand dbCommand = new OracleCommand(sqlquery, Myservice.dbcon))
{
int rowCount = dbCommand.ExecuteNonQuery();
return 1;
}
}
}
public OracleDataReader Query(string sqlquery, Hashtable htData)
{
try
{
OracleDataReader dbReader = null;
Random ran = new Random();
int randomnumber = ran.Next(1,5);
Myservice.dbcon = (OracleConnection) Myservice.htdbcon
["Connection_" +randomnumber];
if (Myservice.dbcon.State != System.Data.ConnectionState.Executing
|| Myservice.dbcon != System.Data.ConnectionState.Fetching)
{
using (OracleCommand dbCommand = new OracleCommand(sqlquery,
Myservice.dbcon))
{
dbReader = dbCommand.ExecuteReader();
}
}
return dbReader;
}
Both the methods are using same connection object.
Since one method uses a lock and the other does not: bad things. No guarantees are made by the object for this scenario, so you should expect it to fail in interesting ways. You should use the same lock object from both places, or better: only use a connection in isolated code, not a shared connection. With connection pooling, it is very rarely useful to have a shared connection object somewhere. A far more suitable pattern is usually to obtain a connection when you need it, and then dispose it. If the underlying provider supports pooling, this will perform ideally, without any issues of synchronization, and will allow parallel queries etc. For example:
using (var conn = SomeUtilityClass.GetOpenConnection())
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = sqlquery;
int rowCount = dbCommand.ExecuteNonQuery();
return 1;
}
and, importantly, do the same from the Query method; no locks, no global shared connections.
I'd also be concerned by the lack of parameters, btw. That suggests you are opening yourself up to SQL injection errors.
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 have a Database class that abstracts the ExecuteNonQuery() and ExecuteReader() of SqlCommand. Due to wrapping the Sqlconnection and SqlCommand around using blocks, the SqlDataReader gets closed after the CustomExecuteReader() is called, therefore I can't read the SqlReaderResultSet at the business level layer. Code below. Thanks guys for the feedback.
public static SqlDataReader SqlReaderResultSet { get; set; }
public static SqlDataReader CustomExecuteReader(string storedProc)
{
using (var conn = new SqlConnection(ConnectionString))
{
var cmd = new SqlCommand(storedProc, conn) {CommandType = CommandType.StoredProcedure};
try
{
conn.Open();
SqlReaderResultSet = cmd.ExecuteReader();
}
catch (InvalidOperationException)
{
if (conn.State.Equals(ConnectionState.Closed))
conn.Open();
}
finally
{
conn.Close();
}
}
return SqlReaderResultSet;
}
"I can't read the SqlReaderResultSet at the business level layer" - and you shouldn't. Data should be passed using data transfer objects, never through a low level data access structure.
I recommend changing your approach so that the method you describe above iterates the records in the datareader, and creates a list of objects. That list of objects is what should be returned and worked on.
Iterator Blocks can be a way around this. It is legal and generally safe to do the following:
IEnumerable<MyFancyData> ResultSet {
get {
using(DbConnection conn = ...)
using(DbCommand cmd = ...) {
conn.Open();
using(DbDataReader reader = cmd.ExecuteReader()) {
while(reader.Read()) {
yield return new MyFancyData(reader[0], reader[42] ...);
}
}
}
}
}
Each time you enumerate the ResultSet property, the connection will be constructed again - and Disposed of afterwards (foreach and other IEnumerator<> consumers will appropriately call the Dispose() method of the generator, allowing the using block to do its thing).
This approach retains the lazy as-you-need it evaluation of the items from the data reader (which can be relevant when your data set becomes large), which still cleaning abstracting away sql-level details from the public API.