2008-09-26 81 views
18

我使用的模式看起来像这样经常。我想知道这是否正常,或者是否有我不在这里申请的最佳做法。当引发异常时,确保SQL连接关闭的正确方法是什么?

具体我想知道;在引发异常的情况下,我在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(); 
    } 
} 
+1

呃......你为什么要检查的连接关闭之前已经关闭?为什么使用类成员来存储连接,如果你要使用它的唯一方法关闭它? – Shog9 2008-09-26 18:46:33

+1

spoon16包含短语“//为了简洁排除某些代码”。由此我推断这不是使用它的唯一方法。 – 2008-09-26 18:52:41

+0

是正确的,这绝对是我能想到的最简单的例子。我认为,由于连接池,我不需要尝试存储每个方法范围之外的SqlConnection对象。所以只要使用USING作为其他建议。 – 2008-09-26 20:19:35

回答

45

总结你的数据库处理代码内部的 “使用”

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

由于您使用IDisposables反正。你可以使用'using'关键字,它基本上等同于在finally块中调用dispose,但它看起来更好。

2

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

这肯定会起作用。我认为习惯上把连接对象本身包含在using语句中,但是如果你想由于某种原因重用相同的连接对象,你所拥有的就很好。

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

-4

我可以建议是:


    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(); 
     } 
    } 

希望帮助:)

1

把连接关闭代码“最后”块内像你这样的表现。最后,块在执行异常之前执行。使用“使用”块也可以,但我发现明确的“最后”方法更清晰。

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

8

.Net Framework保持连接池的原因。相信它! :) 只需连接到数据库并释放连接,就不必编写太多的代码。

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

高度详尽的“解决方案”往往会导致错误的代码。简单更好。

5

MSDN Docs就能很清楚......

  • Close方法回滚任何未决的事务。然后它释放到连接池的连接,或者在连接池被禁用时关闭连接。

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


  • 应用程序可以调用关闭超过一次。没有异常产生。

那么为什么麻烦测试闭?只需调用Close()。


  • 关闭和处置在功能上等同。

这就是为什么使用块导致关闭连接。 使用来电为您处置。


  • 不要调用关闭或Dispose一个连接,一个DataReader或在您的类的Finalize方法的任何其他托管对象。

重要的安全提示。谢谢,埃贡。

1

的答案见这个问题:

Close and Dispose - which to call?

如果您的连接一生是一个单一的方法调用,使用的语言的using功能,以确保连接的正确清理。虽然try/finally功能块在功能上相同,但它需要更多的代码,并且IMO的可读性较差。不需要检查连接的状态,不管怎样,您都可以拨打Dispose来清理连接。

如果您的连接生存期对应于包含类的生存期,则执行IDisposable并清理Dispose中的连接。

0

不需要一个try..finally围绕一个“使用”,使用的IS 一个 try..finally

相关问题