我可以有效地使用这种方法吗?
using(SqlCommand cmd = new SqlCommand("GetSomething", new SqlConnection(Config.ConnectionString))
{
cmd.Connection.Open();
// set up parameters and CommandType to StoredProcedure etc. etc.
cmd.ExecuteNonQuery();
}
我担心的是:SqlCommand的Dispose方法(在退出using块时调用)是否会关闭底层的SqlConnection对象?
答案 0 :(得分:105)
不,处置SqlCommand
不会影响连接。更好的方法是将SqlConnection
包装在一个使用块中:
using (SqlConnection conn = new SqlConnection(connstring))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(cmdstring, conn))
{
cmd.ExecuteNonQuery();
}
}
否则,由于正在使用它的Command被处理掉(也许这就是你想要的?),Connection没有改变。但请记住,连接应该 处置也可能比处理命令更重要。
编辑:
我刚试过这个:
SqlConnection conn = new SqlConnection(connstring);
conn.Open();
using (SqlCommand cmd = new SqlCommand("select field from table where fieldid = 1", conn))
{
Console.WriteLine(cmd.ExecuteScalar().ToString());
}
using (SqlCommand cmd = new SqlCommand("select field from table where fieldid = 2", conn))
{
Console.WriteLine(cmd.ExecuteScalar().ToString());
}
conn.Dispose();
退出使用块时处理第一个命令。连接仍然是开放的,对第二个命令很有用。
因此,处理该命令肯定不会处理它正在使用的连接。
答案 1 :(得分:10)
SqlCommand.Dispose是不够的,因为许多SqlCommand可以(重新)使用相同的SqlConnection。将重点放在SqlConnection上。
答案 2 :(得分:1)
许多地方都弄错了,甚至MS自己的文档。只需记住-在数据库世界中,几乎一切都由不受管理的资源支持,因此几乎所有东西都实现了IDisposable。除非编译器另行通知,否则假定类确实如此。 在使用中包装您的命令。在使用中包装您的连接。在DbProvider上创建连接(从DbProviderFactories.GetFactory获得连接),并在连接上关闭命令,以便在更改基础数据库时,只需更改对DBPF.GetFactory的调用。 因此,您的代码最终应该看起来不错且对称:
var provider = DbProviderFactories.GetFactory("System.Data.SqlClient");// Or MS.Data.SqlClient
using (var connection = provider.CreateConnection())
{
connection.ConnectionString = "...";
using (var command = connection.CreateCommand())
{
command.CommandText = "...";
connection.Open();
using (var reader = command.ExecuteReader())
{
...
}
}
}
答案 3 :(得分:-12)
我使用这种模式。我在我的应用程序中的某个地方有这个私有方法:
private void DisposeCommand(SqlCommand cmd)
{
try
{
if (cmd != null)
{
if (cmd.Connection != null)
{
cmd.Connection.Close();
cmd.Connection.Dispose();
}
cmd.Dispose();
}
}
catch { } //don't blow up
}
然后我总是在try块中创建SQL命令和连接(但不包含在using块中)并且总是有一个finally块:
finally
{
DisposeCommand(cmd);
}
作为命令对象属性的连接对象在这种情况下使用块变得笨拙 - 但是这种模式可以完成工作而不会使代码混乱。