Okay, I've searched "similar" topics but still haven't come across any answer to what I'm going to ask here.
I have a function that creates multiple sql objects under the System.Data.SqlClient namespace. I've read that the using statement disposes of an object after the using block but the variables declared are readonly. My function reuses some of these variables, so I can't really declare them within a using statement.
Here is the body of my function for clarity. Should I call Dispose on the other objects (command, transaction, reader, etc) or will using recursively dispose of them through the connection object? How should I dispose these objects?
I'm still new to C# (I come from C/C++ background) so please forgive me if the question sounds very ignorant.
public string SignIn(string userId, string password)
{
SqlCommand sqlCommand = null;
SqlTransaction sqlTransaction = null;
string sessionId = "";
using(SqlConnection sqlConnection = new SqlConnection Properties.Settings.Default.SessionManagerDBConnectionString))
{
try
{
sqlConnection.Open();
sqlCommand = sqlConnection.CreateCommand();
sqlCommand.CommandText = "GetUserByUserIdPassword";
sqlCommand.CommandTimeout = 30;
sqlCommand.CommandType = CommandType.StoredProcedure;
SqlParameter parameterUserId = sqlCommand.Parameters.Add("@UserId", SqlDbType.NVarChar, 32);
parameterUserId.Value = userId;
SqlParameter parameterPassword = sqlCommand.Parameters.Add("@Password", SqlDbType.NChar, 64);
parameterPassword.Value = this.GetSHA256Hash(password);
sqlTransaction = sqlConnection.BeginTransaction("SampleTransaction");
// more database activity, execute command, store results in datareader
sqlTransaction.Commit();
sqlConnection.Close();
}
catch (SqlException ex)
{
if(sqlTransaction != null)
sqlTransaction.Rollback();
MessageBox.Show(ex.Number + ":" + ex.Message, ex.Server + ":" + ex.Source, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
return sessionId;
}
I tried to search for similar questions again and found some closer answers.
Is SqlCommand.Dispose() required if associated SqlConnection will be disposed?
Does SqlCommand.Dispose close the connection?
I suppose I should add a finally clause to my try-catch and call several Dispose methods there for all the sql objects I've created. I hope that suffices or is there a recommended style of doing this?
finally
{
if(sqlCommand != null)
sqlCommand.Dispose();
if(sqlTransaction != null)
sqlTransaction.Dispose();
...
}
I tried putting a using statement within the try-catch block for one of the sqlCommand objects, but if that part of the code aborts when an exception is thrown, the execution jumps down to the catch portion. The using does not dispose that sqlCommand object.
try
{
...
using(sqlCommand = sqlConnection.CreateCommand())
{
sqlCommand.CommandText = "GetUserByUserIdPassword2";
sqlCommand.CommandTimeout = 30;
sqlCommand.CommandType = CommandType.StoredProcedure;
SqlParameter parameterUserId = sqlCommand.Parameters.Add("@UserId", SqlDbType.NVarChar, 32);
parameterUserId.Value = userId;
SqlParameter parameterPassword = sqlCommand.Parameters.Add("@Password", SqlDbType.NChar, 64);
parameterPassword.Value = this.GetSHA256Hash(password);
SqlDataReader reader = sqlCommand.ExecuteReader(CommandBehavior.SingleRow);
// throws exception, no stored procedure "GetUserByUserIdPassword2"
}
...
}
catch() {}
// sqlCommand still accessible at this point because using above was "aborted".