【问题标题】:using the same instance of SQLCommand more than one time in the same code for more than one query?在同一代码中多次使用同一 SQLCommand 实例进行多次查询?
【发布时间】:2013-11-14 18:23:49
【问题描述】:

我对使用为什么不能在同一代码中多次使用同一 SQLCommand 实例有疑问?

我在这里尝试了代码,它对 gridview 运行良好,但是当我使用 cmd.CommandText() 方法更改查询时,它一直说:

已经有一个打开的 DataReader 与此命令关联,必须先关闭它。

这是代码:

string cs = ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString;
SqlConnection con = new SqlConnection(cs);

try
{
    SqlCommand cmd = new SqlCommand();
    cmd.Connection = con;
    con.Open();
    cmd.CommandText = "Select top 10 FirstName, LastName, Address, City, State from Customers";

    GridView1.DataSource = cmd.ExecuteReader(); 
    GridView1.DataBind();


    cmd.CommandText = "SELECT TOP 10 COUNT(CreditLimit) FROM Customers";
    int total = (int)cmd.ExecuteScalar();
    TotalCreditLble.Text = "The total Credit :" + total.ToString();

}
catch(Exception exp)
{
    Response.Write(exp.Message);
}
finally
{
    con.Close();
}

【问题讨论】:

    标签: c# sqlcommand


    【解决方案1】:

    问题是您使用SqlCommand 对象通过command.ExecuteReader() 命令生成DataReader。当它打开时,您不能重复使用该命令。

    这应该可行:

    using (var reader = cmd.ExecuteReader())
    {
        GridView1.DataSource = reader;
        GridView1.DataBind();
    }
    //now the DataReader is closed/disposed and can re-use command
    cmd.CommandText = "SELECT TOP 10 COUNT(CreditLimit) FROM Customers";
    int total = (int)cmd.ExecuteScalar();
    TotalCreditLble.Text = "The total Credit :" + total.ToString();
    

    【讨论】:

      【解决方案2】:

      已经有一个打开的 DataReader 与此命令关联,必须先关闭。

      这正是您不共享命令的原因。您在代码中的某个地方执行了此操作:

      cmd.ExecuteReader();
      

      但您没有利用命令周围的using 语句,因为您想共享它。你不能那样做。看,ExecuteReader 会在您一次读取一行时打开与服务器的连接;但是该命令现在已锁定,因为此时它是有状态的。正确的方法,总是,是这样的:

      using (SqlConnection c = new SqlConnection(cString))
      {
          using (SqlCommand cmd = new SqlCommand(sql, c))
          {
              // inside of here you can use ExecuteReader
              using (SqlDataReader rdr = cmd.ExecuteReader())
              {
                  // use the reader
              }
          }
      }
      

      这些是非托管资源,需要小心处理。这就是为什么用using 包装它们是必要的。

      不要共享这些对象。构建、打开、使用和处置它们。

      通过利用using,您将永远不必担心关闭和处置这些对象。


      你的代码,写的有点不同:

      var cs = ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString;
      var gridSql = "Select top 10 FirstName, LastName, Address, City, State from Customers";
      var cntSql = "SELECT TOP 10 COUNT(CreditLimit) FROM Customers";
      
      using (SqlConnection con = new SqlConnection(cs))
      {
          con.Open();
      
          try
          {
              using (SqlCommand cmd = new SqlCommand(gridSql, con))
              {
                  GridView1.DataSource = cmd.ExecuteReader(); 
                  GridView1.DataBind();
              }
      
              using (SqlCommand cmd = new SqlCommand(cntSql, con))
              {
                  int total = (int)cmd.ExecuteScalar();
                  TotalCreditLble.Text = "The total Credit :" + total.ToString();
              }
          }
          catch(Exception exp)
          {
              Response.Write(exp.Message);
          }
      }
      

      【讨论】:

      • 我同意你关于不重复使用命令/连接的观点,因为它只会给你带来麻烦。
      【解决方案3】:

      谢谢你们,但感谢那些谈论使用块的人! 为什么这段代码可以正常工作,我在视频示例中看到了它!使用同一个 SqlCommand 实例并通过使用 CommanText 方法和同一个 SqlCommand 实例传递不同的查询是一样的,它执行得很好,这是代码:

      using (SqlConnection con = new SqlConnection(cs))
      {
         SqlCommand cmd = new SqlCommand();
         cmd.Connection = con;
         con.Open();
      
         cmd.CommandText = "Delete from tbleProduct where ProductID= 4";
         int TotalRowsAffected = cmd.ExecuteNonQuery();
         Response.Write("Total rows affected :" + TotalRowsAffected );
      
         cmd.CommandText = "Insert into tbleProduct values (4, 'Calculator', 100, 230)";
         TotalRowsAffected = cmd.ExecuteNonQuery();
         Response.Write("Total rows affected :" + TotalRowsAffected );
      
      
         cmd.CommandText = "ypdate tbleProduct set QtyAvailbe = 234 where ProductID = 2";
         TotalRowsAffected = cmd.ExecuteNonQuery();
         Response.Write("Total rows affected :" + TotalRowsAffected );
      
       }
      

      【讨论】:

        猜你喜欢
        • 2011-06-05
        • 1970-01-01
        • 1970-01-01
        • 2016-09-25
        • 2016-04-07
        • 1970-01-01
        • 1970-01-01
        • 2021-01-06
        • 1970-01-01
        相关资源
        最近更新 更多