I'm using a helper method like this:
private OdbcCommand GetCommand(string sql)
{
string conString = "blah";
var con = new OdbcConnection(conString);
var cmd = new OdbcCommand(sql, con);
return cmd;
}
Then i use it like this:
using (var cmd = GetCommand("select * from myTable")
{
cmd.connection.open();
using(var reader = cmd.ExecuteReader())
{
}
}
Here is a second example:
public static OdbcDataReader GetReader(string conString,string sql)
{
var cmd = GetCommand(conString, sql);
cmd.Connection.Open();
return cmd.ExecuteReader();
}
used like this:
using(var reader = GetReader("blah","select * from blah")
{
}
In these two cases, am i disposing of the connection and cmd objects? I think connection is not being disposed in the first, and neither connection nor cmd in the second, is that right?
Do i need to do i the long way to ensure correct disposal, or is there a shorter approach?
using (var con ...)
using (var cmd)
using (var reader)
In short, if it has Dispose, then you should call it. You can't assume that another object will dispose of an object you pass it for you.
Disposing the command object, will not dispose the connection object, because you can use the connection again after you are done with the command. Disposing of each is the best approach.
For both examples where you wrap your Reader in a using block, you will close the connection with the existing code IF you use the override that accepts a CommandBehavior and set it to 'CloseConnection'
using(var reader = cmd.ExecuteReader(CommandBehavior.CloseConnection)){}
see http://msdn.microsoft.com/en-us/library/s9bz2k02.aspx
Microsoft knows that the connection must remain open while the reader is consumed, and therefore created the option to close the connection when the Reader is closed.
You are correct that the command is not being Disposed in the second example.
Related
I would like to refactor my SqlDataReader code, so it's using using..
SqlDataReader reader = null;
reader = xdCmd.ExecuteReader();
// use reader..
Can I use solution 1) where I declare the reader in the using and first later initialize it with a SqlDataReader, and still get the Dispose "features" using provides? Or do I need to do it as in solution 2), where the initialization happends right away, in the using?
I would guess that 1) is fine, but I'm not sure.
1)
using (SqlDataReader reader = null)
{
xdCmd.CommandText = $"select * from {tableName}";
reader = xdCmd.ExecuteReader();
// use reader..
}
2)
using (SqlDataReader reader = new SqlDataReader(new SqlCommand($"select * from {tableName}"), xdCon))
{
reader = xdCmd.ExecuteReader();
// use reader..
}
The C# language does not include syntax to express the concept of object "ownership" or lifetime management unlike Rust, so it's entirely up to an API's documentation to say if an object's constructor takes ownership of its arguments or not (and thus who gets to call .Dispose()). This is not something the C# compiler can determine for you. However .Dispose() implementations must be idempotent anyway so there is no harm in calling .Dispose() multiple (redundant) times.
Just follow the C# idiomatic conventions of stacked using statements:
using( SqlConnection c = new SqlConnection( connectionString ) )
using( SqlCommand cmd = c.CreateCommand() )
{
await c.OpenAsync().ConfigureAwait(false);
cmd.CommandText = "SELECT foo, bar FROM baz";
using( SqlDataReader rdr = await cmd.ExecuteReaderAsync().ConfigureAwait(false) )
{
...
}
}
for me i prefere to use the second solution it's more subtle , or you can use my example just below :
using (var sqlConnection = new SqlConnection(connection))
{
using (var command = new SqlCommand(query, sqlConnection))
{
using (var read = command.ExecuteReader())
{
// process on your read
}
}
}
Because SqlCommand implements IDisposable, I would normally approach an ADO query as follows.
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(query, connection))
{
// Execute command, etc. here
}
However, what if I need to execute multiple commands during a single connection? Do I really need a new using block for each command?
The examples I found from Microsoft don't use a using block for SqlCommands (or even call Dispose()). What are best practices regarding disposing SqlCommand?
Sure, best practice is to dispose them.
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command1 = new SqlCommand(query1, connection))
{
// Execute command, etc. here
}
using (SqlCommand command2 = new SqlCommand(query2, connection))
{
// Execute command, etc. here
}
using (SqlCommand command3 = new SqlCommand(query3, connection))
{
// Execute command, etc. here
}
}
MSDN probably doesn't show it because it's not really needed in case of SqlCommand. But in my opinion it's bad from microsoft to not use this pattern on every object that implements IDdisosable because people aren't getting used to it.
The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block.
In this case you use using for each command block:
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand cmd1= new SqlCommand(query1, connection))
{
}
using (SqlCommand cmd2= new SqlCommand(query2, connection))
{
}
}
No you do not. There are 2 ways that your multiple commands could be bundled within one connection and command.
The first would be to just reuse the existing CMD object, but changing the CommandText and other CMD.properties as needed.
using (SqlConnection con = new SqlConnection(connectionString)) {
con.Open();
using (SqlCommand cmd = new SqlCommand(query1, con)) {
// cmd.CommandType = CommandType.xxxxx
// add any parameters
// Execute()
cmd.CommandText = query2;
// reset CommandType if needed
// adjust parameters if needed
// Execute()
cmd.CommandText = query 3;
// reset CommandType if needed
// adjust parameters if needed
// Execute()
}
con.Close();
}
The second method would be to create a Stored Procedure on the database server and call that in the one CMD object
-- Database
CREATE PROCEDURE schema.sproc_CommandBatch (
-- any variables here
) AS
BEGIN
-- query 1
-- query 2
-- query 3
END
GO
// C#
using (SqlConnection con = new SqlConnection(connectionString)) {
con.Open();
using (SqlCommand cmd = new SqlCommand("schema.sproc_CommandBatch", con)) {
// cmd.CommandType = CommandType.StoredProcedure
// add any parameters
// Execute()
}
con.Close();
}
Best practice is that if it implements IDisposable then Dispose() it. In fact the examples here do all call Dispose. With a wrinkle:
The first example, where it opens a SqlDataReader, calls .Close() on the command in the finally clause. In fact, .Close is just a wrapper around .Dispose() (and no longer appears in the documentation). Jonathan Wood in his comment pointed out that the Close is on the reader. This is wrong.
For multiple calls on the same connection you can:
Re-use the one command (declared in one using). I don't like this
myself, but that's just me: I find it...ugly.
Use multiple commands in multiple usings. That's what I'd do.
'Best Practice' is a bit amorphous. There's never unanimous agreement that what person A touts as Best Practice is better than what person B is recommending, let alone C, D or E. Use your own judgement.
I've been using
connection.Close();
But this is my first project in .NET and I'm not sure if I'm closing it correctly.
I don't want my website to instantly die after putting it out on real hosting.
Usually I do it this way:
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ToString());
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
// <some code>
conn.Open();
/ <some code>
conn.Close();
You should place the connection in a using statement;
using(var connection = new SqlConnection)
{
connection.Open();
...other code using it here.
}
The using statement ensures that the SqlConnection is disposed when you are done with it. In your scenario (depending on where you put the close method), if an exception is closed, it will never reach the Close() method and the connection will stay open.
Even better is that since you are building a website. There should be a method on the Request object (which should be available) called RegisterForDispose. This will automatically Dispose of the connection (which closes it) when the request ends. You can use it like this:
var connection = new SqlConnection();
Request.RegisterForDispose(connection);
Both accomplish the same thing in the end, but the second allows for more flexibility.
Do what Kevin said and put your .Open() call inside the using block:
using(var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ToString()))
{
var cmd = new SqlCommand("my sql command here", conn);
conn.Open();
cmd.(whatever method you are using)
}
I have 2 methods as below :
internal static SqlDataReader SelectData(string sql)
{
using (var sqlConnection = new SqlConnection(Constant.ConnectionString))
{
sqlConnection.Open();
var sqlCommand = new SqlCommand(sql, sqlConnection);
var dataReader = sqlCommand.ExecuteReader();
return dataReader;
}
}
============
And using this method as :
var dataReader = SelectData(---some sql ---);
private void AddData(dataReader)
{
while (dataReader.Read())
{
Employee e = new Employee();
e.FirstNamei = dataReader["Name"].ToString();
}
dataReader.Close();
}
I know we can merge this two method, but I am looking at better way write this, OR this can cause some problem??
Actually you are in fact leaving yourself open a bit. You really want to write it like this:
using (SqlConnection cnn = new SqlConnection(cnnString))
using (SqlCommand cmd = new SqlCommand(sql, cnn))
{
// use parameters in your SQL statement too, so you can do this
// and protect yourself from SQL injection, so for example
// SELECT * FROM table WHERE field1 = #parm1
cmd.Parameters.AddWithValue("#parm1", val1);
cnn.Open();
using (SqlDataReader r = cmd.ExecuteReader())
{
}
}
because you need to make sure these objects get disposed. Further, by going this direction you don't need dataReader.Close(). It will get called when it gets automatically disposed by the using statement.
Now, wrap that collection of statements inside a try...catch and you're in business.
A couple of things
1) Since you're closing your connection on SelectData, dataReader should blow up on AddData as it requires an open connection
2) AddData shouldn't close dataReader as he didn't open it.
3) Maybe you're hiding some code but I don't see that you use Employee instance created on AddData
Technically, first method would be correct if you would do
sqlCommand.ExecuteReader(CommandBehavior.CloseConnection);
Then, your client would close the reader and your connection will be closed as well.
Second example would also be correct if you didn't close the reader inside of it. There is no criminal in passing the reader to a method just to iterate it. but it has to be controlled from where it was created. How you open and dispose of it - this is different question.
I know that a lot of examples exist where a SqlConnection is defined and then a SqlCommand is defined, both in Using blocks:
using (var conn = new SqlConnection(connString)) {
using (var cmd = new SqlCommand()) {
cmd.Connection = conn;
//open the connection
}
}
My question: If I define the connection directly on the SqlCommand, does the connection close when the command is disposed?
using (var cmd = new SqlCommand()) {
cmd.Connection = new SqlConnection(connString);
//open the connection
}
No, SqlCommand never attempts to close/dispose of the connection.
No, the connection object will not be disposed until you dispose it explicitly. But my recommendation is to use using blocks whenever you can.
It does not close the connection, you need to either close it yourself or put it in its own using statment.
Also here is a tip to make your using blocks a bit more readable:
using (var conn = new SqlConnection(connString))
using (var cmd = new SqlCommand())
{
cmd.Connection = conn;
}
#milot
But my recommendation is to use using blocks whenever you can.
Using Using Blocks is nice but useless when working with non IDisposable Objects and so this can be confusing if you use Using Blocks anywhere.
Be careful since your objects might not being Disposed if they don't implements IDisposable.
Hope this helps.