Disposing of SqlConnection before Disposing of SqlCommand - c#

I have a method like this:
void Execute(SqlCommand cmd)
{
try
{
using(SqlConnection conn = new SqlConnection(...))
{
conn.Open();
cmd.Connection = conn;
// ...
}
}
finally
{
cmd.Connection = null;
}
}
It's used like this:
using(SqlCommand cmd = new SqlCommand(...))
{
Execute(cmd);
}
Is there anything behaviorally wrong with this? I know it's more usual to create the SqlConnection first, then the SqlCommand, but since SqlCommand is in reality more-or-less a plain old object I think it should be fine in practice.

I highly recommend to rethink about refactoring to find better solution.
But in your scenario
You can safety dispose connection before disposing command.
They are not related to each other and you can safety remove connection from a command object or even set it to another connection.
The only important thing is command must have an open connection before execute.
Removing connection before finally section make disposing of connection faster.
I recomend to rewrite your code to something like this:
void Execute(SqlCommand cmd)
{
try
{
using (SqlConnection conn = new SqlConnection(""))
{
conn.Open();
cmd.Connection = conn;
// Execute command and get data
// It is better to remove connection from command here
cmd.Connection = null;
}
}
catch
{
// Remove connection if there is error
cmd.Connection = null;
}
}

Related

What is the proper way of calling multiple "SQL DataReader"s in C#?

I call ExecuteReader(); to get data, then i need to get another data with another query. My structure's been always like this :
class SomeClass
{
public static void Main(String[] args)
{
SqlConnection sqlConn = new SqlConnection();
sqlConn.ConnectionString = "some connection string"
SqlCommand SQLCmd = new SqlCommand();
SQLCmd.CommandText = "some query";
SQLCmd.Connection = sqlConn;
sqlConn.Open();
sqlReader = SQLCmd.ExecuteReader();
while (sqlReader.Read())
{
//some stuff here
}
sqlReader.Dispose();
sqlReader.Close();
sqlConn.Close();
SQLCmd.CommandText = "another query";
sqlConn.Open();
sqlReader = SQLCmd.ExecuteReader();
while (sqlReader.Read())
{
//some other stuff here
}
sqlReader.Dispose();
sqlReader.Close();
sqlConn.Close();
}
}
They share the same connection string. What else can they share ? Can they share same sqlConn.Open(); ? What is the proper way of resource allocating and avoiding errors ?
BTW it works as it is. Thanks in advance.
This is how I would write all of that:
class SomeClass
{
public static void Main(String[] args)
{
using (SqlConnection sqlConn = new SqlConnection("some connection string"))
{
sqlConn.Open();
using (SqlCommand comm = new SqlCommand("some query", conn))
using (var sqlReader = comm.ExecuteReader())
{
while (sqlReader.Read())
{
//some stuff here
}
}
using (SqlCommand comm = new SqlCommand("some query", conn))
using (var sqlReader = comm.ExecuteReader())
{
while (sqlReader.Read())
{
//some other stuff here
}
}
}
}
}
The using statement handles disposing of items when the block is finished. As for sharing stuff, you could leave the connection open across the commands.
The most important thing to dispose out of all of that would be the connection, but I tend towards honouring a using statement if an item is IDisposable regardless of what it actually does in the background (which is liable to change as it's an implementation detail).
Don't forget, there is also Multiple Active Result Sets (as demonstrated in this answer) from a single command and a single reader, where you advance the reader onto the next result set.
My slightly more flippant answer to how I might write all of that would be:
return connection.Query<T>(procedureName, param, commandType: CommandType.StoredProcedure);
Using Dapper ;-)
As alluded to in my comment - if possible, combine the two queries into one and then (if it still produces multiple result sets), use NextResult to move on.
Stealing Adam's structure, but with that change:
class SomeClass
{
public static void Main(String[] args)
{
using (SqlConnection sqlConn = new SqlConnection("some connection string"))
{
sqlConn.Open();
using (SqlCommand comm = new SqlCommand("some query; some other query;", conn))
using (var sqlReader = comm.ExecuteReader())
{
while (sqlReader.Read())
{
//some stuff here
}
if(sqlReader.NextResult())
{
while (sqlReader.Read())
{
//some other stuff here
}
}
}
}
}
}
The proper way is to wrap SqlConnections and SqlCommands in using-statements. This will force Dispose to be invoked on the objects when the using block is left, even if an Exception is thrown. (This is not the case with your current code.)
Something in the line of
using(var cnn = new SqlConnection("connectionstring")){
cnn.Open();
using(var cmd = new SqlCommand("SELECT 1")){
var reader = cmd.ExecuteReader();
while(reader.Read()) { /* doStuff */ }
}
}
Regardless of the approach Close/Dispose will not actually close the connection since connection setup is very expensive. It will just return the connection to a connection pool and allow other commands/readers to use it.
To manage resource you can use using like as shown under
...
SQLCmd.CommandText = "some query";
SQLCmd.Connection = sqlConn;
sqlConn.Open();
//using will dispose reader automatically.
using(sqlReader = SQLCmd.ExecuteReader())
{
while (sqlReader.Read())
{
//some stuff here
}
}
//sqlReader.Dispose();
//sqlReader.Close();
//sqlConn.Close();
SQLCmd.CommandText = "another query";
//no need to open connection again.
// sqlConn.Open();
// sqlReader = SQLCmd.ExecuteReader();
using(sqlReader = SQLCmd.ExecuteReader())
{
while (sqlReader.Read())
{
//some stuff here
}
}
//sqlReader.Dispose();
//sqlReader.Close();
//sqlConn.Close();
you can use using only for those classes which have implemented IDispose interface.
in your example you can use SqlConnection and SqlCommand also with using code block.
Use 'using', you don't need to manually close and dispose.
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command = new SqlCommand("spTest", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#employeeid", employeeID));
command.CommandTimeout = 5;
command.ExecuteNonQuery();
}
Open a new connection every time you need it is a best practices. ADO.net use connection pool to menage connection.
http://msdn.microsoft.com/it-it/library/8xx3tyca(v=vs.110).aspx
Dont forget your try catch statements though :)
class SomeClass
{
public static void Main(String[] args)
{
using (SqlConnection sqlConn = new SqlConnection("some connection string"))
{
try{
sqlConn.Open();
using (SqlCommand comm = new SqlCommand("some query", conn))
using (var sqlReader = comm.ExecuteReader())
{
while (sqlReader.Read())
{
//some stuff here
}
}
using (SqlCommand comm = new SqlCommand("some query", conn))
using (var sqlReader = comm.ExecuteReader())
{
while (sqlReader.Read())
{
//some other stuff here
}
}
}
catch()
{
// Do exception catching here or rollbacktransaction if your using begin transact
}
finally
{
sqlConn.Close();
}
}
}
}

Replacement for SqlConnection and SqlCommand

I have been writing a lot of open and close connection to a Microsoft SQL Server database. I'm not sure whether it is the latest technique available for .NET. Is there any latest .NET function that I'm missing?
Example code:
protected string InjectUpdateToProductDBString(string Command, TextBox Data, string TBColumn)
{
string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["AuthenticationDBConnectionString"].ConnectionString;
SqlConnection con = new SqlConnection(connectionString);
con.Open();
SqlCommand cmd = new SqlCommand(command, con);
cmd.Parameters.AddWithValue("#" + TBColumn, Data.Text.ToString());
cmd.ExecuteNonQuery();
con.Close();
return "Data successfully updated";
}
Is there any replacement for this fussy code technique? Just a discussion to improve my code technique.
There are other ways to write it and other tools you could use (like Entity Framework).
However, I recommend that you create a static function (or several) for your data access calls.
protected DataTable ExecuteSqlDataReader(string connection, string sqlQuery, SqlParameter[] cmdParams)
{
MySqlConnection con = new MySqlConnection(connection);
MySqlCommand cmd = new MySqlCommand(sqlQuery, con);
cmd.Parameters = cmdParams;
MySqlDataAdapter sda = new MySqlDataAdapter(cmd);
DataTable dt = new DataTable();
sda.Fill(dt);
sda.Command.Close();
return dt;
}
Create methods for Getting a dataTable, One value, ExecuteNonQuery, and even break it further down by abstracting out the SqlCommand creation to it's own method.
In any project, this code should be written only a few times.
Make sure that you enclose your SqlConnection in using statement. It will ensure the connection is closed even if there is an exception. Also, enclose your SqlCommand object in using statement, that will ensure disposal of unmanaged resources.
In your current code snippet if there is an exception at cmd.ExecuteNonQuery(); then your line con.Close would not execute, leaving the connection open.
So your method could be like:
protected string InjectUpdateToProductDBString(string Command, TextBox Data, string TBColumn)
{
string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["AuthenticationDBConnectionString"].ConnectionString;
using (SqlConnection con = new SqlConnection(connectionString))
{
con.Open();
using (SqlCommand cmd = new SqlCommand(command, con))
{
cmd.Parameters.AddWithValue("#" + TBColumn, Data.Text.ToString());
cmd.ExecuteNonQuery();
}
}
return "Data successfully updated";
}
Later you can return a DataTable or List<T> for your returned rows from the query.
If you want to move away from ADO.Net, then you can look into Object-Relation Mapping (ORM), which would provide you objects based on your database and easier way to manage your code base. Entity framework is one of them. You may see https://stackoverflow.com/questions/132676/which-orm-for-net-would-you-recommend
private SqlConnection GetConnection()
{
var con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["AuthenticationDBConnectionString"].ConnectionString);
con.Open();
return con;
}
protected string InjectUpdateToProductDBString(string Command, TextBox Data, string TBColumn)
{
using (var con = GetConnection())
{
using (var cmd = con.CreateCommand())
{
cmd.Parameters.AddWithValue("#" + TBColumn, Data.Text);
cmd.ExecuteNonQuery();
return "Data Succesfully Updated";
}
}
}

Is this defensive code or are there possibilities that it could encouter problems?

I've got the following code which makes a connection to a db > runs a stored proc > and then moves on.
I believe it is easy to get db programming wrong so it is important to be defensive: is the following defensive? (or can it be improved?)
public int RunStoredProc()
{
SqlConnection conn = null;
SqlCommand dataCommand = null;
SqlParameter param = null;
int myOutputValue;
try
{
conn = new SqlConnection(ConfigurationManager.ConnectionStrings["IMS"].ConnectionString);
conn.Open();
dataCommand = conn.CreateCommand();
dataCommand.CommandType = CommandType.StoredProcedure;
dataCommand.CommandText = "pr_blahblah";
dataCommand.CommandTimeout = 200; //seconds
param = new SqlParameter();
param = dataCommand.Parameters.Add("#NumRowsReturned", SqlDbType.Int);
param.Direction = ParameterDirection.Output;
dataCommand.ExecuteNonQuery();
myOutputValue = (int)param.Value;
return myOutputValue;
}
catch (SqlException ex)
{
MessageBox.Show("Error:" + ex.Number.ToString(), "Error StoredProcedure");
return 0;
}
finally
{
if (conn != null)
{
conn.Close();
conn.Dispose();
}
}
}
CODE NOW LOOKS LIKE THE FOLLOWING
I've tried to use all the help offered by everyone and the above code has now been amended to the following which I hope is now sufficiently defensive:
public SqlConnection CreateConnection()
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["IMS"].ConnectionString);
return conn;
}
public int RunStoredProc()
{
using (var conn = CreateConnection())
using (var dataCommand = conn.CreateCommand())
{
conn.Open();
dataCommand.CommandType = CommandType.StoredProcedure;
dataCommand.CommandText = "pr_BankingChargebacks";
dataCommand.CommandTimeout = 200; //5 minutes
SqlParameter param = new SqlParameter();
param = dataCommand.Parameters.Add("#NumRowsReturned", SqlDbType.Int);
param.Direction = ParameterDirection.Output;
dataCommand.ExecuteNonQuery();
int myOutputValue = (int)param.Value;
return myOutputValue;
}
}
Try using, well, the using construct for such things.
using(var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["IMS"].ConnectionString)
{
}
Once you do that, I think you will be at the right level of "defense". Similarly try to do the same for anything that has to be disposed ( like the command)
There is no need to call both .Close() and .Dispose()
Prefer the using block instead of try-finally
Dispose of the command object
I would remove the catch clause. It doesn't belong here (though YMMV).
If you are going to write this code all over the place, stop. At least create a small helper class to do this, or use a light-weight 'ORM' like Massive, Dapper or PetaPoco. For an example of an ADO.Net helper class, see https://github.com/jhgbrt/yadal/blob/master/Net.Code.ADONet.SingleFile/Db.cs.
The main thing I would notice is a MessageBox in database-access code. I can't think of a single scenario that is useful. Just let the exception rise. Don't catch that.
As a general template:
using(var conn = CreateConnection())
using(var cmd = conn.CreateCommand())
{
// setup cmd and the parameters
conn.Open();
cmd.ExecuteNonQuery();
// post-process cmd parameters (out/return/etc)
}
Note: no Close(), no catch; all the finally are handled by the using. Much simpler; much harder to get wrong.
Another thing to emphasise is the use of a factory method for creating the connection; don't put:
new SqlConnection(ConfigurationManager.ConnectionStrings["IMS"].ConnectionString)
into every method; after all... that could change, and it is unnecessary repetition.
If MessageBox.Show("Error:" + ex.Number.ToString(), "Error StoredProcedure"); is how you're going to handle an exception then you're not logging or even retrieving the actual exception details.
In addition to manojlds's advice I recommend that you make yourself some reusable helper methods to call the database. For example, make yourself a method that reads the connection string, creates the connection and opens it. Don't repeat infrastructure stuff everywhere.
You can do the same for invoking an sproc or a command text.

Is the database connection in this class "reusable"?

I'm new to asp.net so this might be really basic question, but i cant figure it out.
I found a bit of code on the internet, that connects to database. And i created a namespace and some classes to use the same code in different projects.
The code and my class is the following:
namespace databaseFunctions
{
public class databaseConnection
{
private static string databaseConnectionString()
{
return "DRIVER={MySQL ODBC 5.1 Driver}; ........";
}
public static DataTable getFromDatabase(string SQL)
{
DataTable rt = new DataTable();
DataSet ds = new DataSet();
OdbcDataAdapter da = new OdbcDataAdapter();
OdbcConnection con = new OdbcConnection(databaseConnectionString());
OdbcCommand cmd = new OdbcCommand(SQL, con);
da.SelectCommand = cmd;
da.Fill(ds);
try
{
rt = ds.Tables[0];
}
catch
{
rt = null;
}
return rt;
}
public static Boolean insertIntoDatabase(string SQL)
{
OdbcDataAdapter da = new OdbcDataAdapter();
OdbcConnection con = new OdbcConnection(databaseConnectionString());
OdbcCommand cmd = new OdbcCommand(SQL, con);
con.Open();
try
{
cmd.ExecuteNonQuery();
return true;
}
catch
{
return false;
}
}
}
There is no problem getting data from database, or insert data into some database.
But. when i try to get the last_insert_id() from the mysql database. i only get a zero.
This is why i think that this piece of code I've created and copied from internet, creates a new connection for every time i call the "getFromDatabase(SQL)"
Is there anyone that could help me with fixing this class getFromDatabase() to keep the databaseconnection alive until i tell the program to abandon the connection?
I guess it is the "new OdbcConnection" that should be changed? Is it possible to check if there already is a connection alive?
I've done this hundreds of times in classic asp, but now, with classes and stuff. I'm totally lost.
The problem you face is that you've coded yourself into a "new connection per action" corner. What you really want to aim for,and is considered best practice, is "new connection per batch of actions".
What I recommend in this case is to open connection when required, and close when disposed. What we'll do is move the odbc adapters to a larger scoped variable so that it can be accessed within the class.
namespace databaseFunctions
{
public class databaseConnection:IDisposable
{
private OdbcConnection con;
private string connectionString;
public databaseConnection(string connectionString){
this.connectionString = connectionString;
}
public void OpenConnection(){
if (con == null || con.IsClosed ){ // we make sure we're only opening connection once.
con = new OdbcConnection(this.connectionString);
}
}
public void CloseConnection(){
if (con != null && con.IsOpen){ // I'm making stuff up here
con.Close();
}
}
public DataTable getFromDatabase(string SQL)
{
OpenConnection();
DataTable rt = new DataTable();
DataSet ds = new DataSet();
OdbcCommand cmd = new OdbcCommand(SQL, con);
da.SelectCommand = cmd;
da.Fill(ds);
try
{
rt = ds.Tables[0];
}
catch
{
rt = null;
}
return rt;
}
public Boolean insertIntoDatabase(string SQL)
{
OpenConnection();
OdbcCommand cmd = new OdbcCommand(SQL, con);
con.Open();
try
{
cmd.ExecuteNonQuery();
return true;
}
catch
{
return false;
}
}
// Implementing IDisposable method
public void Dispose(){
CloseConenction();
}
}
}
Now the next time you use your class do something like
using (DatabaseConnection db = new DatabaseConnection()){
db.InsertIntoDatabase(...);
db.GetLastInsertID();
db.GetFromDatabase(...);
}
At the end of that code block, because it is IDisposeable, it will close that connection for you in the dispose method.
Things I changed:
implemented IDisposable interface
changed methods from static to class methods.
added new methods for opening closing connection
moved connection variable to class level scope
added an argument to the constructor that lets you pass in a connection string (you should put this connection string in you Web.Config
Edits:
constructor takes in connectionString per suggestion.
Yes, the code you posted is creating a new database connection every time a method is called, but that's not a problem. The problem is that it is not disposing the connection properly. The way to handle something like this is as follows:
using (OdbcConnection con = new OdbcConnection("yourconnectionsstring"))
{
con.open();
OdbcCommand command = new OdbcCommand("command_text",con);
command.ExecuteQuery(); //or what ever you need to do
}
That way the connection is being disposed properly since using is just syntactic sugar for try/finally
What you need to do is execute the 2 sql statements in the same transaction in a way that you insert the record in the first sql statement and retrieve the last inserted id on the next insert before ending the transaction. For example:
using (OdbcConnection con = new OdbcConnection("yourconnectionsstring"))
{
con.open();
OdbcTransaction tran = con.BeginTransaction()
OdbcCommand command = new OdbcCommand("first_sql_statement_here",con);
command.ExecuteNonQuery();
command.CommandText = "select last_insert_id();";
int result =command.ExecuteScalar();
tran.commit();
}
That is pretty much the idea.
You should let the connection pool handle your connections; That means you Close() every connection as soon as possible, and only create a new one at the last possible moment.
So yes - keep creating new ones for separate transactions.

Multiple SQL queries asp.net c#

I need to run several queries inside one function, will I have to create a new SqlConnection for each? Or having one connection but different SqlCommands works too?
Thanks,
EDIT: Will this work?
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(query1, conn))
{
cmd.ExecuteNonQuery();
}
using (SqlCommand cmd = new SqlCommand(query2, conn))
{
cmd.ExecuteNonQuery();
}
using (SqlCommand cmd = new SqlCommand(query3, conn))
{
cmd.ExecuteNonQuery();
}
}
Using the MDSN Documentation as a base:
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string sql1 = "SELECT ID,FirstName,LastName FROM VP_PERSON";
string sql2 = "SELECT Address,City,State,Code FROM VP_ADDRESS";
using (SqlCommand command = new SqlCommand(sql1,connection))
{
//Command 1
using (SqlDataReader reader = command.ExecuteReader())
{
// reader.Read iteration etc
}
} // command is disposed.
using (SqlCommand command = new SqlCommand(sql2,connection))
{
//Command 1
using (SqlDataReader reader = command.ExecuteReader())
{
// reader.Read iteration etc
}
} // command is disposed.
// If you don't using using on your SqlCommands you need to dispose of them
// by calling command.Dispose(); on the command after you're done.
} // the SqlConnection will be disposed
It doesn't matter which way you go.
SqlConnections are pooled by the operating system. You could literally open and close a connection thousands of times in a row and not incur any performance or other penalty.
How it works is:
Application makes a request to create a db connection (var c = new SqlConnection(...))
The Operating Systems connection pool looks to see if it has a connection sitting idle. If it does, you get a reference to that. If not then it spins up a new one.
Application indicates it is finished with the connection (c.Dispose())
Operating System keeps the connection open for a certain amount of time in case your app, or another one, tries to create another connection to that same resource.
If that connection stays idle until a timeout period passes then the OS finally closes and releases.
This is why the first time you make a connection to a database it might take a second to start before the command(s) can be processed. However if you close it and reopen it then the connection is available immediately. More information is here: http://msdn.microsoft.com/en-us/library/8xx3tyca(v=vs.110).aspx
Now, as to your code, generally speaking you open 1 SqlConnection each time you make a SqlCommand call; however, it is perfectly acceptable/reasonable to make multiple SqlCommand calls while within the same block under the SqlConnection using clause.
Just bear in mind that you do NOT want to keep a SqlConnection object hanging around in your code for any longer than is absolutely necessary. This can lead to a lot of potential issues, especially if you are doing web development. Which means it's far better for your code to open and close 100 SqlConnection objects in rapid succession than it is to hold onto that object and pass it around through various methods.
Having one SqlConnection and many SqlCommands will work fine, however you must make sure that you dispose of any SqlDataReaders that are returned from previous commands before attempting to run additional commands.
using (SqlConnection conn = new SqlConnection())
{
conn.Open()
using (SqlCommand cmd = new SqlCommand("SELECT myrow FROM mytable", conn))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
// Handle first resultset here
}
}
using (SqlCommand cmd = new SqlCommand("SELECT otherrow FROM othertable", conn))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
// Handle second resultset here
}
}
}
Alternaitvely you might be able to combine your commands up into one batch and instead process multiple resultsets, like this:
using (SqlConnection conn = new SqlConnection())
{
conn.Open()
using (SqlCommand cmd = new SqlCommand("SELECT myrow FROM mytable; SELECT otherrow FROM othertable", conn))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
// Handle first resultset here, and then when done call
if (reader.NextResult())
{
// Handle second resultset here
}
}
}
}
When you are processing many resultsets you will find that batching together queries like this can significantly improve performance, however it comes at the price of added complexity in your calling code.
Open only one SQLConnection
Use the keyworkd Using as it will automatically dispose the connection.
If you open connection for each one , it can have performance problems.
Example:
using (SqlConnection con = new SqlConnection(connectionString))
{
//
// Open the SqlConnection.
//
con.Open();
//
// The following code shows how you can use an SqlCommand based on the SqlConnection.
//
using (SqlCommand command = new SqlCommand("SELECT TOP 2 * FROM Dogs1", con))
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine("{0} {1} {2}",
reader.GetInt32(0), reader.GetString(1), reader.GetString(2));
}
}
}
One more example:
public DataTable GetData()
{
DataTable dt = new DataTable();
using (SqlConnection con = new SqlConnection("your connection here")
{
con.Open();
using (SqlCommand cmd = con.CreateCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "your stored procedure here";
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
}
}
return dt;
}
Purely as an alternative to the using statements:
SqlConnection con = new SqlConnection(myConnectionString);
SqlCommand cmd = con.CreateCommand();
cmd.CommandText = #"SELECT [stuff] FROM [tableOfStuff]";
con.Open();
SqlDataReader dr = null;
try
{
dr = cmd.ExecuteReader();
while(dr.Read())
{
// Populate your business objects/data tables/whatever
}
}
catch(SomeTypeOfException ex){ /* handle exception */ }
// Manually call Dispose()...
if(con != null) con.Dispose();
if(cmd != null) cmd.Dispose();
if(dr != null) dr.Dispose();
The major difference between this and the using statements, is this will allow you to handle exceptions more cleanly.

Categories

Resources