using block for command object close connection? - c#

I am a bit confused on the below coding. Are they both the same? If not, which one is the best and why?
//Two using blocks for Command and Connection
using (var cn = new OracleConnection(connectionString))
using (var cmd = new OracleCommand(sql, cn))
{
}
//One using block for Command and Connection
using (var cmd = new OracleCommand(sql, new OracleConnection(connectionString)))
{
}

First assuming that you accidently added an extra ) (otherwise neither will even compile) then the first example will properly dispose of both the command and the connection where as the second will only dispose of the command.
Here is the equivalent code for the first.
OracleConnection cn = new OracleConnection(connectionString);
try
{
OracleCommand cmd = new OracleCommand(sql, cn);
try
{
// Use cmd and cn here.
}
finally
{
if(cmd != null)
((IDisposable)cmd).Dispose();
}
}
finally
{
if(cn != null)
((IDisposable)cn).Dispose();
}
and the second.
OracleCommand cmd = new OracleCommand(sql, new OracleConnection(connectionString));
try
{
// Use cmd here.
}
finally
{
if(cmd != null)
((IDisposable)cmd).Dispose();
}
Also note that you can only create multiple instances that will all get disposed in one using if they are all the same type. As the following example from the MSDN page about using shows.
using (Font font3 = new Font("Arial", 10.0f),
font4 = new Font("Arial", 10.0f))
{
// Use font3 and font4.
}

Related

C# Transactionscope multiple connections

I'm trying to execute a query to multiple databases by using a TransactionScope.
Here is my code; I want to execute the query on two different SQL Server databases, but in my code, while the query on the first connection executes without a problem, the second connection.Open() gets stuck.
// connList : connection string List
// query : to execute query
public DataSet SendQueryMultiConnection(List<string> connList, string query)
{
using(TransactionScope scope = new TransactionScope())
{
DataSet retDs = new DataSet();
try
{
foreach(string conn in connList)
{
if (string.IsNullOrEmpty(conn))
throw new Exception("No ConnectionData");
using (SqlConnection connection = new SqlConnection(conn))
{
connection.Open();
using (SqlCommand command = new SqlCommand(query, connection))
{
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
DataTable dt = new DataTable();
adapter.Fill(dt);
retDs.Tables.Add(dt);
}
}
}
}
scope.Complete();
}
catch (Exception ex)
{
//...
}
return redDs;
}
}
I can't guess a clue, what is the problem in my code?
Thanks for reading.

SignalR SqlDependency breaks when I make SqlCommand generic

I am using SignalR to receive updates made to the database. I tried to make my method for doing this generic as shown below, however, this breaks the SQL dependency as it does not fire when there is a change in the DB. I have narrowed down the source of the problem to the SQL command which seems to stop it from working.
public IEnumerable<T> GetAllMessages<T>() where T : new()
{
var messages = new List<T>();
using (var connection = new SqlConnection(_connString))
{
connection.Open();
using (var command = new SqlCommand(#"SELECT * FROM [dbo]." + typeof(T).Name, connection))
{
command.Notification = null;
var dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
if (connection.State == ConnectionState.Closed)
connection.Open();
var reader = command.ExecuteReader();
while (reader.Read())
{
var row = new T();
ConvertReaderToRelevantModel(reader, row);
messages.Add(row);
}
}
}
return messages;
}
If I change the SQL command to the snippet below it works as expected:
using (var command = new SqlCommand(#"SELECT [ID],
[Name], [Number], [DateLastUpdated] FROM [dbo].[HeartBeats]", connection))
What is stopping this from working and how can I resolve this issue?
typef(T).Name is not what you expect. put a breakpoint and take a look.

explicitly dispose NpgsqlParameters

Do I really need to explicitly dispose of NpgsqlParameters?
Code I am using goes below:
using (var connection = new NpgsqlConnection(connectionstring))
{
connection.Open();
using (var command = new NpgsqlCommand())
{
command.Connection = connection;
command.CommandText = "Select * from mytable where column1=:pcolumn1 AND column2=:pcolumn2";
command.Parameters.AddRange(new NpgsqlParameter[2]{
new NpgsqlParameter{ ParameterName="pcolumn1", Value=val1},
new NpgsqlParameter{ ParameterName="pcolumn2", Value=val2}
});
using (var reader=command.ExecuteReader())
{
while (reader.Read())
{
//read reader here
}
}
}
}
NpgsqlParameter is inherited from DbParameter and ICloneable. Neither of these implement IDisposable so you don't need to dispose NpgsqlParameters.

How to use Using statement for multiple instances?

I want to use using for SqlConnection and SqlCommand objects to dispose those. How can I use in this scenario?
for example:
using (sqlConnection = new SqlConnection(IRLConfigurationManager.GetConnectionString("connectionStringIRL")))
{
}
But here I am using connection based on the if condition.
SqlConnection _sqlConnection;
SqlCommand sqlCmd;
DBPersister per = (DBPersister)invoice;
if (per == null)
{
_sqlConnection = new SqlConnection(IRLConfigurationManager.GetConnectionString("connectionStringIRL"));
sqlCmd = new SqlCommand("usp_UpdateDocumentStatusInImages", _sqlConnection);
}
else
{
_sqlConnection = per.GetConnection();
sqlCmd = per.GenerateCommand("usp_UpdateDocumentStatusInImages", _sqlConnection, per);
}
sqlCmd.CommandType = CommandType.StoredProcedure;
//mycode
try
{
if (_sqlConnection.State == ConnectionState.Closed)
_sqlConnection.Open();
sqlCmd.ExecuteNonQuery();
}
catch
{
throw;
}
finally
{
if (per == null)
invoice._sqlConnection.Close();
}
You can nest them, like this:
using (var _sqlConnection = new SqlConnection(...))
{
using (var sqlCmd = new SqlCommand(...))
{
//code
}
}
Use the conditional operator to determine what to assign to each variable:
using(SqlConnection _sqlConnection = per==null?
new SqlConnection(IRLConfigurationManager.GetConnectionString("connectionStringIRL"))
: per.GetConnection())
using(SqlCommand sqlCmd = per==null?
new SqlCommand("usp_UpdateDocumentStatusInImages", _sqlConnection);
: per.GenerateCommand("usp_UpdateDocumentStatusInImages",
_sqlConnection, per))
{
//Code here using command and connection
}
Although I must say, per.GenerateCommand(..., per) looks like an odd function (it's an instance method that also must be passed an instance of the same class - must it always be the same instance?)

Using MySQLConnection in C# does not close properly

I try to write a class to make MySql Connections easier. My problem is, after I open a connection and close it. It is still open in the Database and gets aborted.
I'm using the 'using' statement' of course, but the connection is still open and gets aborted after I exit the program.
Here's what my code looks like:
using (DatabaseManager db = new DatabaseManager())
{
using (MySqlDataReader result = db.DataReader("SELECT * FROM module WHERE Active=1 ORDER BY Sequence ASC"))
{
foreach (MySqlDataReader result in db.DataReader("SELECT * FROM module WHERE Active=1 ORDER BY Sequence ASC"))
{
//Do stuff here
}
}
}
The class Database manager opens the connection and closes it when disposed:
public DatabaseManager()
{
this.connectionString = new MySqlConnectionStringBuilder("Server=localhost;Database=businessplan;Uid=root;");
connect();
}
private bool connect()
{
bool returnValue = true;
connection = new MySqlConnection(connectionString.GetConnectionString(false));
connection.Open();
}
public void Dispose()
{
Dispose(true);
}
public void Dispose(bool disposing)
{
if (disposing)
{
if (connection.State == System.Data.ConnectionState.Open)
{
connection.Close();
connection.Dispose();
}
}
//GC.SuppressFinalize(this);//Updated
}
//Updated
//~DatabaseManager()
//{
// Dispose(false);
//}
So, I checked it in the debugger and the Dispose()-method is called and executes correctly.
What am I missing? Is there something I did wrong or misunderstood?
Just in case, the DataReader()-method (Updated version):
public IEnumerable<IDataReader> DataReader(String query)
{
using (MySqlCommand com = new MySqlCommand())
{
com.Connection = connection;
com.CommandText = query;
using (MySqlDataReader result = com.ExecuteReader(System.Data.CommandBehavior.CloseConnection))
{
while (result.Read())
{
yield return (IDataReader)result;
}
}
}
}
Ok, I tried to use the yield return:
foreach (MySqlDataReader result in db.DataReader("SELECT * FROM module WHERE Active=1 ORDER BY Sequence ASC"))
{
//...
}
And I changed the DataReader-method:
public IEnumerable<IDataReader> DataReader(String query)
{
using (MySqlCommand com = new MySqlCommand())
{
com.Connection = connection;
com.CommandText = query;
using (MySqlDataReader result = com.ExecuteReader())
{
while (result.Read())
{
yield return (IDataReader)result;
}
}
}
}
It works in the way that I can retrieve the data, yet I still have the same problem: The connection isn't closed properly.
Im unsure about mysqlconnection but the sql server counter part uses Connection pooling and does not close when you call close instead it puts it in the connection pool!
Edit: Make sure you dispose the Reader, Command, and Connection object!
Edit: Solved with the ConnectionString Parameter "Pooling=false" or the static methods MySqlConnection.ClearPool(connection) and MySqlConnection.ClearAllPools()
You need to wrap the Command and the DataReader in using statements as well.
According to the mysql docs, the MySQLConnection is not closed when it goes out of scope. Therefore you must not use it inside a using.
Quote...
"If the MySqlConnection goes out of scope, it is not closed. Therefore, you must explicitly close the connection by calling MySqlConnection.Close or MySqlConnection.Dispose."
Have a look at using something like this:
private static IEnumerable<IDataRecord> SqlRetrieve(
string ConnectionString,
string StoredProcName,
Action<SqlCommand> AddParameters)
{
using (var cn = new SqlConnection(ConnectionString))
using (var cmd = new SqlCommand(StoredProcName, cn))
{
cn.Open();
cmd.CommandType = CommandType.StoredProcedure;
if (AddParameters != null)
{
AddParameters(cmd);
}
using (var rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
while (rdr.Read())
yield return rdr;
}
}
}

Categories