Dispose如何调用ADO.NET对象?

时间:2011-04-12 22:41:17

标签: c# ado.net idisposable

实现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())
            {

            }
        }
    }
}

或者这个实现是依赖的,所以它可能使用一个数据库的提供者但不能用于另一个数据库吗?

5 个答案:

答案 0 :(得分:4)

最佳策略是使用块中的所有ADO.NET对象 - 完全停止。

对各种ADO.NET对象的一点反射显示,如果没有关闭/处置,事情会或多或少地掉在地板上。这种影响很大程度上取决于你正在使用哪些提供商 - 如果你使用的是非托管句柄(ODBC,OleDb等),你可能会泄漏内存,因为我没有看到任何东西在终结者的方式。如果它是一个全托管的提供者(例如,SqlClient),它最终会得到清理,但是根据你所持有的对象,你最终可能会在数据库服务器上保留的资源比你想要的要长很多

答案 1 :(得分:1)

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

答案 2 :(得分:1)

单独处理它们。 Reader和Command对象完全可能在其dispose例程中执行更多操作,而不仅仅是破坏连接(现在或将来的ADO.NET版本)。因此,为了(a)明确和(b)安全,你应该单独处理它们。

他们实现IDisposable的事实表明你应该在完成对象时总是运行Dispose例程,所以最好不要尝试再次猜测界面,它不会给你任何好处,而你可能最终会泄漏记忆和处理。

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

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

看起来比(在我看来)更整洁,而不是嵌套。

答案 3 :(得分:0)

你应该单独处理它们。即使处置IDbConnection会将所有内容都置于封面(我不知道它是否确实存在,我也不关心,因为接下来的原因),你应该在将来时编程。明天有人会编辑该代码并在同一个连接上发出一个新命令,然后它会想知道为什么他会收到一个连接仍然在使​​用的错误(因为IDataReader没有被处理掉)。

答案 4 :(得分:0)

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

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

希望这会有所帮助。