我可以有效地使用这种方法吗?
1 2 3 4 5 6
| 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对象?
否,处置SqlCommand不会影响连接。更好的方法是将SqlConnection也包装在using块中:
1 2 3 4 5 6 7 8
| using (SqlConnection conn = new SqlConnection(connstring))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(cmdstring, conn))
{
cmd.ExecuteNonQuery();
}
} |
否则,由于使用了连接的命令已被处理(也许正是您想要的?),因此该连接不变。但是请记住,连接应该
也要被处置,并且处置可能比命令更重要。
编辑:
我刚刚测试了这个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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(); |
退出using块时,将处理第一个命令。该连接仍处于打开状态,对于第二个命令来说是好的。
因此,处置该命令绝对不会处置其正在使用的连接。
SqlCommand.Dispose是不够的,因为许多SqlCommand可以(重新)使用相同的SqlConnection。将重点放在SqlConnection上。
许多地方都弄错了,甚至MS自己的文档。只需记住-在数据库世界中,几乎所有内容都由不受管理的资源支持,因此几乎所有内容都实现IDisposable。除非编译器另行通知,否则假定类确实起作用。
在使用中包装命令。将您的连接包装在使用中。在DbProvider上创建连接(从DbProviderFactories.GetFactory获得连接),并在连接上关闭命令,以便在更改基础数据库时,只需更改对DBPF.GetFactory的调用。
因此,您的代码最终应该看起来不错且对称:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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())
{
...
}
}
} |
我使用这种模式。我的应用程序中某处有此私有方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 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块设置为:
1 2 3 4
| finally
{
DisposeCommand(cmd);
} |
在这种情况下,连接对象是命令对象的属性,这使using块变得笨拙-但是此模式可以完成工作而不会使您的代码混乱。