3

关于这个主题的另一个话题,因为我厌倦了阅读无数主题以找到我的问题的答案:)

假设我们有以下类:

public class MyClass
{
   private const string conString = "connection string";

   private int Operation()
   {
      int count = 0;

      using(var con = SqlConnection(conString))
      {
         string select_cmd = "SELECT * FROM TABLE";

         using(var cmd = new SqlCommand(select_cmd, con))
         {
            using(var reader = cmd.ExecuteReader())
            {
               while(reader != null && reader.Read())
                  count++;
            }
         }
      }

      return count;
   }

}

由于与数据库的连接是在 using 语句中实例化的,因此 con.close() 和最终 con.dispose() 方法将被调用,是否需要为 MyClass 实现 IDisposable?MyClass 超出范围时会被垃圾收集吗?

编辑:

谢谢你的回复,这就是我的想法,但我需要说清楚。还有一个问题。

如果我的类有几个 Operations() 在数据库上做一些工作,从资源消耗的角度来看,拥有一个 SqlConnection 成员,实例化并在类构造函数上打开它并实现 IDisposable 以关闭它而不是更好的做法在每个操作中使用“使用”语句(在每个操作中打开和关闭数据库)?当然,那样我应该只在 using 语句中实例化和使用 MyClass 对象。

4

3 回答 3

3

不,您只需要实现 IDisposable 如果您的类在 Operation() 方法之外持有 SqlConnection 实例,这样它就可以与类本身保持活动状态(例如,如果您将它分配给类成员字段或财产)。

在您的类超出范围之前,SqlConnection 实例将被标记为符合清理条件,因为该实例超出了 using 块中的范围。最重要的是,非托管数据库连接(由 SqlConnection 封装)已通过 Dispose 调用释放。当 GC 感到有足够的压力证明进行 GC 通过时,SqlConnection 的托管部分将被释放。

至于您的类实例,它也将由 GC 自行决定释放,除非您在应用程序的整个生命周期内创建和销毁大量类实例,否则您无需担心这一点(我想数百万)。

编辑

对于第二个问题,最好为每个方法使用和处理 SqlConnection 实例,因为这个特定的数据库客户端类在内部实现了连接池(即:当你处理它一段时间时它并没有真正关闭连接,所以当一个新的SqlConnection 被创建它重用打开连接池中的一个)。

请参阅(旧但有效):http: //msdn.microsoft.com/en-us/library/8xx3tyca%28v=vs.71%29.aspx

如果您使用没有实现自己的池的数据库客户端 API,最好按照您的建议手动管理它。但是,您必须小心同步对连接的访问​​(即:不要让 2 个线程同时使用它)并自己管理生命周期问题(例如:如果您的类在应用程序的所有持续时间内都保持活动状态,那么您将无限期打开数据库资源......等等)

大多数现代的(MySql Connector.NET、SQL Server)都实现了池化。

于 2012-04-24T12:24:46.187 回答
1

完成Operation()后,该方法中使用的所有非托管资源都将被释放。它没有理由实施IDisposableMyClass不会打开任何非托管资源,因此不需要实现该接口。

关于您的第二个问题,您的类的实例将像任何其他托管对象一样被垃圾收集。

于 2012-04-24T12:23:34.993 回答
0

不,不需要实现 IDisposable 接口,你没有资源可以释放。

于 2012-04-24T12:23:51.217 回答