Reputation: 920
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.
Upvotes: 2
Views: 5494
Reputation: 64557
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.
return connection.Query<T>(procedureName, param, commandType: CommandType.StoredProcedure);
Using Dapper ;-)
Upvotes: 5
Reputation: 1893
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();
}
}
}
}
Upvotes: 0
Reputation: 86
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.
Upvotes: 1
Reputation: 3191
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
Upvotes: 0
Reputation: 239824
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
}
}
}
}
}
}
Upvotes: 5
Reputation: 15086
The proper way is to wrap SqlConnection
s and SqlCommand
s 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.
Upvotes: 1
Reputation: 3455
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();
}
Upvotes: 0