抛出exception时,确保SQL连接关闭的正确方法是什么?

我经常使用看起来像这样的模式。 我想知道这是否正常,或者是否有最佳实践我不在这里申请。

我特别想知道; 在抛出exception的情况下,我在finally块中的代码足以确保连接被正确关闭?

public class SomeDataClass : IDisposable { private SqlConnection _conn; //constructors and methods private DoSomethingWithTheSqlConnection() { //some code excluded for brevity try { using (SqlCommand cmd = new SqlCommand(SqlQuery.CountSomething, _SqlConnection)) { _SqlConnection.Open(); countOfSomething = Convert.ToInt32(cmd.ExecuteScalar()); } } finally { //is this the best way? if (_SqlConnection.State == ConnectionState.Closed) _SqlConnection.Close(); } //some code excluded for brevity } public Dispose() { _conn.Dispose(); } } 

将数据库处理代码包装在“使用”中

 using (SqlConnection conn = new SqlConnection (...)) { // Whatever happens in here, the connection is // disposed of (closed) at the end. } 

出于某种原因,.Net Framework保留了连接池。 相信它! :)您不必编写如此多的代码来连接数据库并释放连接。

您可以使用’using’语句并放心’IDBConnection.Release()’将为您关闭连接。

高度精细的“解决方案”往往会导致错误的代码。 简单就是更好。

MSDN Docs让这个很清楚……

  • Close方法回滚所有挂起的事务。 然后,它会释放与连接池的连接,或者在禁用连接池时关闭连接。

您可能没有(并且不希望)禁用连接池,因此在您调用“关闭”后,池最终会管理连接状态。 这可能很重要,因为在所有打开的连接中从数据库服务器端看可能会感到困惑。


  • 应用程序可以多次调用Close。 没有exception生成。

那么为什么还要关闭Closed的测试呢? 只需调用Close()即可。


  • 关闭和处置在function上是等效的。

这就是使用块导致闭合连接的原因。 使用呼叫为您处理。


  • 不要在类的Finalize方法中对Connection,DataReader或任何其他托管对象调用Close或Dispose。

重要的安全提示。 谢谢,Egon。

我猜你的意思是“_SqlConnection.State == ConnectionState.Closed”!=。

这肯定会奏效。 我认为在using语句中包含连接对象本身更为习惯,但是如果你想因某种原因重用同一个连接对象,那么你所拥有的就是好的。

但是,你应该改变的一件事是Dispose()方法。 您不应该在dispose中引用连接对象,因为它可能已在该点完成。 您应该遵循推荐的Dispose模式。

因为你无论如何都在使用IDisposables。 您可以使用’using’关键字,这基本上等同于在finally块中调用dispose,但它看起来更好。

看到这个问题的答案:

关闭和处理 – 要打电话?

如果您的连接生命周期是单个方法调用,请使用该语言的usingfunction来确保正确清除连接。 虽然try/finally块在function上是相同的,但它需要更多代码而IMO的可读性更低。 无需检查连接状态,无论如何都可以调用Dispose ,它将处理清理连接。

如果您的连接生命周期对应于包含类的生命周期,则实现IDisposable并清除Dispose的连接。

将连接关闭代码放在像您显示的“Finally”块中。 最后,在抛出exception之前执行块。 使用“使用”块也可以,但我发现明确的“终结”方法更清晰。

使用语句对许多开发人员来说都是老生常谈,但年轻的开发人员可能不知道这一点。

没有必要尝试。最终围绕“使用”,使用IS一试..最终

我可以这样建议:

 class SqlOpener : IDisposable { SqlConnection _connection; public SqlOpener(SqlConnection connection) { _connection = connection; _connection.Open(); } void IDisposable.Dispose() { _connection.Close(); } } public class SomeDataClass : IDisposable { private SqlConnection _conn; //constructors and methods private void DoSomethingWithTheSqlConnection() { //some code excluded for brevity using (SqlCommand cmd = new SqlCommand("some sql query", _conn)) using(new SqlOpener(_conn)) { int countOfSomething = Convert.ToInt32(cmd.ExecuteScalar()); } //some code excluded for brevity } public void Dispose() { _conn.Dispose(); } } 

希望有所帮助:)