【问题标题】:C# IDisposable Using: Best PracticeC# IDisposable 使用:最佳实践
【发布时间】:2011-10-21 18:28:53
【问题描述】:

我已经将 OracleConnection 和 OracleCommand 对象包装在 USING 语句中已有一段时间了,但是,在运行代码分析器之后,我发现 OracleParameter 也实现了 IDisposable。下面的代码是否正确?是否有更好的可读性或结构技术?乍一看,它似乎只是杂乱无章的 USING 语句:

using (OracleConnection conn = new OracleConnection(connectionstring))
{
    conn.Open();
    using (OracleCommand cmd = new OracleCommand(sql, conn))
    {
        cmd.BindByName = true;

        using (OracleParameter param1 = new OracleParameter("p1", OracleDbType.Int32, System.Data.ParameterDirection.Input))
        {
            param1.Value = int.Parse(value1);
            cmd.Parameters.Add(param1);
        }

        using (OracleParameter param2 = new OracleParameter("p2", OracleDbType.Varchar2, System.Data.ParameterDirection.Input))
        {
            param2.Value = value2;
            cmd.Parameters.Add(param2);
        }

        using (OracleDataReader dr = cmd.ExecuteReader())
        {
            // loop data here...
        }
    }
}

【问题讨论】:

    标签: c# coding-style idisposable using


    【解决方案1】:

    您只想在参数使用结束时处理参数,包括在查询期间(可能还有结果的读取):

    using (OracleConnection conn = new OracleConnection(connectionstring))
    {
        conn.Open();
        using (OracleCommand cmd = new OracleCommand(sql, conn))
        {
            cmd.BindByName = true;
    
            using (OracleParameter param1 = new OracleParameter("p1", OracleDbType.Int32, System.Data.ParameterDirection.Input))
            using (OracleParameter param2 = new OracleParameter("p2", OracleDbType.Varchar2, System.Data.ParameterDirection.Input))
            {
                param1.Value = int.Parse(value1);
                cmd.Parameters.Add(param1);
                param2.Value = value2;
                cmd.Parameters.Add(param2);
    
                using (OracleDataReader dr = cmd.ExecuteReader())
                {
                    // loop data here...
                }
            }
        }
    }
    

    请注意,您可以将多个 using 语句放在一行中。这是因为,就像if 语句一样,

    1. using 语句被视为简单语句(即使带有块);和
    2. using 语句可以采用块或下面的语句。

    【讨论】:

    • 虽然有很多类似的答案,但我感谢您提供了示例和评论。
    • 谢谢!很高兴我能帮上忙。 :-)
    【解决方案2】:
    using (OracleConnection conn = new OracleConnection(connectionstring)) 
    using (OracleCommand cmd = new OracleCommand(sql, conn)) 
    using (OracleParameter param1 = new OracleParameter("p1", OracleDbType.Int32,
           System.Data.ParameterDirection.Input)) 
    using (OracleParameter param2 = new OracleParameter("p2", OracleDbType.Varchar2,
           System.Data.ParameterDirection.Input)) 
    }
        conn.Open(); 
        cmd.BindByName = true; 
    
        param1.Value = int.Parse(value1); 
        cmd.Parameters.Add(param1); 
    
        param2.Value = value2; 
        cmd.Parameters.Add(param2); 
    
        using (OracleDataReader dr = cmd.ExecuteReader()) 
        { 
            // loop data here... 
        } 
    } 
    

    【讨论】:

      【解决方案3】:

      我不确定它是否能正常工作。考虑到在使用结束时,两个参数都应该被释放。您的cmd.Parameters 对象仍然持有对它们的引用这一事实并不排除OracleParameter Dispose 方法中可能发生的事情。出于所有密集目的,该特定对象的开发人员可能正在清除您的 OracleCommand 期望填充的字段。

      那里有一些危险。如果您绝对确定要正确处理您的OracleParameters,我建议您在使用OracleDataReader 之后处理它们。

      请记住,当您使用完对象后,通常会调用Dispose。您是在告诉它释放它保留在池中的所有资源。如果您没有使用完一个对象,请不要过早地处理它。

      【讨论】:

        【解决方案4】:

        你能看一下连接和命令源代码,它是否配置了参数?如果连接或命令对象处置模式包装参数并在处置它们时处置它们。你应该担心它。我认为它会/应该。

        【讨论】:

          【解决方案5】:

          根据MSDN,你只需要对ConnectionDataReader对象使用using。我从未见过using(或.Dispose())与ADO.NET 参数对象一起使用。如果这是必要的,甚至是可取的,我认为在过去 10 年中已经有一段时间了。

          【讨论】:

          • MSDN 正在讨论 BCL 提供的对象。 Oracle 对这些的实现很可能需要处理参数。如果他们不打算被处置,他们为什么要实施 IDisposable?
          • 或者他们很可能不会。我从未见过任何在参数对象上调用 Dispose() 或将其放在 using 块中的 ADO.NET 代码(用于 Oracle 的实现或其他任何人的)。同样,如果需要处理参数,那么很久以前就会出现这种情况。
          • 所以您的建议是,即使一个对象实现了 IDisposble,除非已知存在问题,否则不要丢弃它?听起来对我来说是个坏建议。
          • 可以很容易地走安全胜于遗憾的路线并处置,但我真的认为甲骨文搞砸了这一点,他们的处置方法可能没有做任何有意义的事情。
          【解决方案6】:

          不,这是不正确的,因为您甚至在使用参数之前就已对其进行了处理。

          相反,你应该这样

          OracleParameter param1 = new OracleParameter("p1", OracleDbType.Int32, System.Data.ParameterDirection.Input);
          
          param1.Value = int.Parse(value1);
          cmd.Parameters.Add(param1);
          
          
          OracleParameter param2 = new OracleParameter("p2", OracleDbType.Varchar2, System.Data.ParameterDirection.Input);
          
          param2.Value = value2;
          cmd.Parameters.Add(param2);
          
          
          using (OracleDataReader dr = cmd.ExecuteReader())
          {
            // loop data here...
          }
          
          param1.dispose();
          param2.dispose();
          

          【讨论】:

            【解决方案7】:

            此代码不正确。您创建的参数仍然在using 语句范围之外使用,因为您将它们添加到参数集合中,但是using 语句将在控制离开范围时对参数调用Dispose。这意味着到了使用命令中的参数的时候,它们已经被抛弃了

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-12-23
              • 2013-11-08
              • 1970-01-01
              • 2013-12-28
              • 2020-05-29
              • 1970-01-01
              相关资源
              最近更新 更多