我通常使用这样的代码:
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString))
{
var command = connection.CreateCommand();
command.CommandText = "...";
connection.Open();
command.ExecuteNonQuery();
}
我的command
会自动处理吗?或者不是,我必须把它包装到using
块?是否需要处理SqlCommand
?
这样做:
using(var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString))
using(var command = connection.CreateCommand())
{
command.CommandText = "...";
connection.Open();
command.ExecuteNonQuery();
}
不在命令上调用dispose也不会做任何太糟糕的事情。然而,在它上面调用Dispose将supress the call to the finalizer,使调用dispose性能增强。
最安全的策略是,如果它明确地或通过使用块实现Dispose()
,则始终在对象上调用IDisposable
。可能存在不需要它但无论如何调用它应该永远不会引起问题(如果类正确写入)的情况。此外,您永远不知道实现何时可能会改变意味着以前不需要呼叫的地方现在肯定是必需的。
在您给出的示例中,您可以为命令添加额外的内部使用块,以及为连接维护外部使用块。
是的,您应该,即使它实现当前没有做太多,您也不知道将来如何更改它(例如更新的框架版本)。通常,您应该将所有实现IDisposable
的对象置于安全的一边。
但是,如果操作延迟并且您不控制整个范围(例如,当异步工作或返回SqlDataReader
时),您可以将CommandBehavior
设置为CloseConnection
,以便在读取器完成后立即执行连接已正确关闭/处理。
你可以使用Reflector或dotPeek或https://referencesource.microsoft.com/找到这种东西。
我有一个很小的挖掘(我建议你挖掘自己虽然完全确定其余部分虽然因为我没有那么努力)并且看起来当你杀死一个连接时没有任何关联的孩子与那个连接。此外,它实际上看起来并不像命令的处理实际上那么多。它会将一个字段设置为null,从容器中分离(这可能会阻止托管内存泄漏)并引发一个事件(这可能很重要,但我看不到谁在听这个事件)。
无论哪种方式,最好在使用块中使用这些东西,或者确保使用保存连接的对象中的dispose模式处理它(如果您打算暂停命令一段时间)。
在实践中,你可以跳过Dispose
。它不释放任何资源。它甚至没有抑制自SQLCommand constructor does that以来的最终确定。
理论上,微软可能会改变实现以保存非托管资源,但我希望他们能够在他们这么做之前就推出一个能够摆脱Component
基类的API。
在我看来,为Dispose
和SqlConnection
调用SqlCommand
是一种很好的做法,使用下面的代码
using(var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString))
try{
using(var command = connection.CreateCommand())
{
command.CommandText = "...";
connection.Open();
command.ExecuteNonQuery();
}
}
catch(Exception ex){ //Log exception according to your own way
throw;
}
finally{
command.Dispose();
connection.Close();
connection.Dispose();
}