2

我对使用为什么不能在同一代码中多次使用同一 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();
}
4

3 回答 3

5

问题是您正在使用该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();
于 2013-11-14T18:32:01.440 回答
5

已经有一个与此命令关联的打开的 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);
    }
}
于 2013-11-14T18:32:07.923 回答
0

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

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 );

 }
于 2013-11-14T20:02:00.143 回答