【问题标题】:c# sql what to dispose时间:2019-05-10 标签:c#sql要处理什么
【发布时间】:2010-11-12 14:53:19
【问题描述】:

我有下面的代码来从存储过程中查询记录,但我担心我可能不会处理我需要的东西,或者当垃圾收集器不久之后将清除对象时我正在处理。

是否需要处理 SqlDataReader,因为它位于 try catch 块中?

我需要同时运行 cmd.Dispose 和 cmd.Connection.Close 还是一个推断另一个?

垃圾收集器最终会处理掉所有这些对象(可能不够及时),还是因为使用了非托管代码而隐含地需要处理这些对象?

public void GetData(string studentID)
    {
        SqlCommand cmd = new SqlCommand("sp_stored_proc", 
                new SqlConnection(Settings.Default.connectionString)) 
                { CommandType = CommandType.StoredProcedure };
        try
        {
            cmd.Connection.Open();
            cmd.Parameters.AddWithValue("@student_id", studentID);
            SqlDataReader dr = cmd.ExecuteReader();

         //do something with the data

            if (dr != null)
                dr.Dispose();
        }
        catch
        {
            //error handling
        }
        finally
        {
            if (cmd != null)
            {
                cmd.Dispose();
                cmd.Connection.Close();
            }

        }

    }

【问题讨论】:

    标签: c# sql


    【解决方案1】:

    您应该配置数据读取器和命令。如果您处置该命令,则无需单独关闭连接。理想情况下,您应该同时使用 using 块:

    using (SqlCommand cmd = new...)
    {
        // do stuff
        using (SqlDataReader dr = cmd.ExecuteReader())
        {
            // do stuff
        }
    }
    

    如果您需要异常处理,请在 using 块内部或周围单独进行 - 尽管使用 using,但对于 Dispose 调用不需要 finally。

    【讨论】:

    • 如果我可以多次投票,我会的。来吧人们!使用使用块!
    • 释放SqlCommand 对象将不会释放SqlConnection。这很容易测试。 stackoverflow.com/questions/60919/is-sqlcommand-dispose-enough/…
    • 即使我处置命令,我也必须处置阅读器吗?即使我处置了连接,我也必须处置命令吗?您可以向我们推荐任何来源吗?
    【解决方案2】:

    如果你使用这样的东西:

    public void GetData(string studentID)
    {
        using (SqlConnection connection = new SqlConnection(Settings.Default.connectionString))
        {
            connection.Open();
    
            using (SqlCommand command = connection.CreateCommand())
            {
                command.CommandType = CommandType.StoredProcedure;
                command.CommandText = "sp_stored_proc";
                command.Parameters.AddWithValue("@student_id", studentID);
    
                using (SqlDataReader dataReader = command.ExecuteReader())
                {
                    // do something with the data
                }
            }
        }
    }
    

    那么您的所有 Disposable 对象都会被正确处理。在 SqlConnection、SqlCommand 和 SqlDataReader 对象上调用 Dispose()(这是 using 块在退出时所做的事情)正确地关闭它们。

    此外,这种方法将所有变量的范围限定在它们的使用位置。

    这种方法的缺点是,如果您需要使用 try/catch 进行错误处理,则必须将其包裹在整个方法体中,或者使用其中的几个来处理连接错误,而不是读取错误等。 .

    【讨论】:

      【解决方案3】:

      我是否需要处理 SqlDataReader 因为它在 try catch 内 屏蔽?

      -- 是的,因为在try catch里面不会调用dispose方法。

      我需要同时运行 cmd.Dispose 和 cmd.Connection.Close 还是两者都可以推断?

      -- 是的,您需要同时运行两者。调用 Cmd.dispose 不会关闭连接。

      dispose 方法旨在供程序员用来清理不由垃圾收集器直接管理的资源,或者在程序完成使用它们以释放空间后需要清除的资源。从技术上讲,可以设置程序以便 GC 处理它的处理,但这是我不会做出的假设,特别是因为编写类的程序员为您公开了 dispose 方法。将 Command 放在 using 语句中可能是最简单的方法,因为您知道它会在代码离开声明空间时被释放。

      using (var connection  = new Connection ())
      {
         using (var cmd = new Command())
         {
      
      
      
         }
      }
      

      【讨论】:

      • “不,cmd.dispose 将关闭连接” - 我认为这是不正确的;据我所知,在命令上调用 Dispose 与它的连接无关。
      • @Kevin:您链接到的帖子指出,在 连接对象 上调用 Dispose 将在同一对象上调用 close。页面上没有出现“命令”一词。
      • 我不相信我犯了那个错误。在我考虑了一秒钟之后,命令对象不会关闭连接对象是完全有道理的。哇!
      【解决方案4】:

      就个人而言,如果某些东西有 dispose 方法,那么无论如何都值得使用它,因为它们可以防止潜在的内存泄漏。

      【讨论】:

        【解决方案5】:

        长话短说;如果它实现了IDisposable,你应该调用Dispose

        即使您使用 Reflector 来确定一个对象中的 Dispose 在另一个对象上调用 Dispose,我仍然建议在两者上调用 Dispose,因为 这是可能会更改的内部实现细节 在未来的某个版本中,所以你不应该依赖它总是正确的。

        所以,Dispose 任何 IDisposable

        【讨论】:

          【解决方案6】:

          你应该首先通过 Connection.Open(); 然后使用SqlDataReader等方法读取 毕竟先关闭SqlDataReader再关闭连接

          你可以使用关键字“using”来处理它,但这不是一个好主意

          其实关键字“using”就是自动处理对象。 也就是说,对象应该实现dispose方法

          【讨论】:

          • 请详细说明为什么在这种情况下使用构造是一个坏主意。
          猜你喜欢
          • 2020-06-15
          • 2020-10-01
          • 2015-06-14
          • 2011-07-08
          • 2012-02-03
          • 2017-04-15
          • 2021-07-31
          • 2016-01-27
          • 1970-01-01
          相关资源
          最近更新 更多