繁体   English   中英

如何在ADO.NET对象上调用Dispose?

[英]How is Dispose called on ADO.NET objects?

实现IDbConnectionIDbCommandIDataReader的数据库访问类都实现IDisposable ,但是显然Command和Reader依赖于Connection。 我的问题是,我是否必须分别对每个这些对象都进行Dispose()处理,还是将Connection对象的处理也对其他对象进行处理?

也就是说,我可以这样做并保证我不会冒任何未托管资源未被释放的风险:

using (IDbConnection conn = GetConnection())
{
      IDbCommand cmd = conn.CreateCommand();
      cmd.CommandText = " ..... ";
      IDataReader rdr = cmd.ExecuteReader();
      while (rdr.Read())
      {

      }
}

还是我必须这样做:

using (IDbConnection conn = GetConnection())
{
    using (IDbCommand cmd = conn.CreateCommand())
    {
        cmd.CommandText = " ..... ";
        using (IDataReader rdr = cmd.ExecuteReader())
        {
            while (rdr.Read())
            {

            }
        }
    }
}

还是此实现依赖于某项实现,因此它可能会使用一个数据库的提供程序,而不是另一个数据库的提供程序?

最佳策略是在使用句点(句号)时使用所有ADO.NET对象。

在各种ADO.NET对象上进行一些Reflector-ing表示,如果未关闭/未放置,则事物或多或少会掉在地板上。 这样做的效果在很大程度上取决于您使用的提供程序-如果您使用的是下面带有非托管句柄的内容(ODBC,OleDb等),则可能会泄漏内存,因为我什么也没看到以终结器的方式。 如果它是一个全托管的提供程序(例如SqlClient),它将最终得到清理,但是根据您持有的对象,最终可能会使数据库服务器上的资源使用时间比您想要的长得多。

您应单独处理它们,也可以使用此处提供的解决方案。

分别处理它们。 Reader和Command对象完全有可能在其处置例程中做更多的事情,而不仅仅是销毁连接(现在或将来的ADO.NET版本)。 因此,为了(a)明确而(b)安全,您应该将它们全部单独处置。

他们实现了IDisposable的事实表明,在完成对象处理后,您应该始终运行Dispose例程,因此最好不要尝试再猜测一下接口,它不会给您带来任何好处,并且您可能最终导致内存和句柄泄漏。

using语句嵌套时,您可以做一些事情来使代码看起来更整洁。 例如:

(using SqlConnection conn = new SqlConnection())
(using SqlCommand comm = new SqlCommand())
{
    //Do stuff
}

(我认为)这比嵌套括号更整洁。

您应该单独处理它们。 即使部署IDbConnection可以将所有内容都隐藏起来(我不知道它是否确实如此,也由于以下原因我不在乎),您也应该在将来时进行编程。 明天有人会编辑该代码并在同一连接上发出新命令,然后会怀疑为什么他会得到一个错误,指出该连接仍在使用中(因为没有处置IDataReader)。

using语句的主要优点是资源释放管理。 通常,.NET Framework垃圾收集器控制资源的分配和释放。 使用using语句,我们可以控制它。 因此,using语句实现了一个IDisposible接口,该接口包含一个公共Dispose()方法。

同样,您始终可以始终手动调用Dispose()方法以从内存中释放资源或对象。

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM