【问题标题】:CA2000 object 'comm' is not disposed along all exception pathsCA2000 对象“comm”未沿所有异常路径设置
【发布时间】:2011-03-08 21:48:47
【问题描述】:

我在 VS 2010 中的 DAL 中有很多类似的方法。当我运行“新”代码分析选项时,我收到消息 - 警告 CA2000 对象 'comm' 未沿所有异常路径处理。在对对象“comm”的所有引用超出范围之前调用 System.IDisposable.Dispose。

我知道我可以为 SQLCommand 使用另一个 using 语句,但是如果我喜欢像使用 Try/Finally 块那样做的话。我的理解是 finally 块最后执行并进行清理。有人在这里看到我的 dispose 调用有什么问题吗?

  public List<Product> GetAllProducts()
    {

        List<Product> prodList = new List<Product>();
        using (SqlConnection connection = new SqlConnection(GetConnection()))
        {
            SqlCommand comm = new SqlCommand("GetAllProducts", connection);
            connection.Open();
            comm.CommandType = CommandType.StoredProcedure;
            SqlDataReader dr = comm.ExecuteReader();
            try
            {
                while (dr.Read())
                {
                    Product obj = new Product();
                    obj.ProductID = Convert.ToInt32(dr["ProductID"].ToString());
                    obj.Product = dr["Product"].ToString();
                    //etc....                                                                       

                    prodList.Add(obj);
                }
            }
            finally
            {
                comm.Dispose();
                dr.Close();
            }
        }

        return prodList;
    }

}

【问题讨论】:

    标签: c# asp.net


    【解决方案1】:

    如果这三个语句中的任何一个抛出异常,comm 将不会被释放。

            connection.Open();
            comm.CommandType = CommandType.StoredProcedure;
            SqlDataReader dr = comm.ExecuteReader();
    

    您的 try 块也需要包含这些语句。

    【讨论】:

    • 如果我这样做了,那么我必须从 finally 块中删除 dr.cose(),因为我收到一条错误消息“当前上下文中不存在名称 dr”。这有意义吗?我只是想如果发生错误,我希望 dr.close 专门位于 finally 块中..
    • 您需要处理两个不同的对象,它们分配在不同的行上。这意味着您要么需要使用两个 try/finally 块,要么需要将其中一个初始化为 null 并确保在调用 dispose 之前它不为 null。
    • 我想我从来没有见过 2 Try finally 块,对我来说听起来不正确。我刚刚实现了 using (SqlCommand comm = new SqlCommand("GetAllProducts", connection)) 并且代码分析仍然说“在对对象'comm'的所有引用超出范围之前调用 System.IDisposable.Dispose。”并在对对象“连接”的所有引用超出范围之前调用 System.IDisposable.Dispose。
    【解决方案2】:

    在 command 和 dataReader 周围放置一个 using 块,以便它们始终被释放。

    public List<Product> GetAllProducts()
    {
        List<Product> prodList = new List<Product>();
        using (SqlConnection connection = new SqlConnection(GetConnection()))
        {
            using (SqlCommand comm = new SqlCommand("GetAllProducts", connection))
            {
                connection.Open();
                comm.CommandType = CommandType.StoredProcedure;
                using (SqlDataReader dr = comm.ExecuteReader())
                {
                    try
                    {
                        while (dr.Read())
                        {
                            Product obj = new Product();
                            obj.ProductID = Convert.ToInt32(dr["ProductID"].ToString());
                            obj.Product = dr["Product"].ToString();
                            //etc....                                                                       
    
                            prodList.Add(obj);
                        }
                    }
                }
            }
        }
    
        return prodList;
    }
    

    【讨论】:

      【解决方案3】:
              List<Measure_Type> MeasureList = new List<Measure_Type>();
              SqlConnection conn = null;            
      
              SqlDataReader rdr = null;
              SqlCommand cmd = null;
              try
              {
                  conn = new SqlConnection();
                  conn.ConnectionString = System.Configuration.ConfigurationManager.AppSettings["Conn"];
                  conn.Open();
                  cmd = new SqlCommand("SELECT Measure_ID, Mea_Name FROM MeasureTable WHERE IsActive=1", conn);
      
                  rdr = cmd.ExecuteReader();
                  if (rdr.HasRows == true)
                  {
                      while (rdr.Read())
                      {
                          MeasureTypeList.Add(new Measure_Type { MeasureTypeID = Convert.ToInt32(rdr[0]), MeasureTypeName = rdr[1].ToString() });
                      }
                  }
              }
      
              catch (Exception ex)
              {
                  ExceptionPolicy.HandleException(ex, "Log");
              }
              finally
              {
                  cmd.Dispose();
                  // close the reader
                  if (rdr != null) { rdr.Close(); }
                  // Close the connection
                  if (conn != null) { conn.Dispose(); }
              }
              return MeasureTypeList;
      

      在try块内创建conn = new SqlConnection();,然后打开它来解决这个bug。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-06-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-20
        • 2011-09-03
        相关资源
        最近更新 更多