简体   繁体   English

如何解决“已经有一个使用此命令打开数据阅读器”的错误?

[英]How to solve "there is already an open data reader with this command" error?

My code goes like this我的代码是这样的

SqlDataReader read=command1.ExecuteReader();
while(reader.Read())
{
    // based on each data read from a table1 I want to run an update query on table1 itself
    SqlCommand command2= new SqlCommand();//command with update query and connection is the same as command1

    command2.ExecuteNonQuery();
}//end of while

The error occurs at command2.ExecuteNonQuery().错误发生在 command2.ExecuteNonQuery()。

Is there a way to go around this problem?有没有办法解决这个问题的go?

I am using the same connection for both commands.我对这两个命令使用相同的连接。

Edit,full code is given below.编辑,完整代码如下。 I read data from shoporder table to a data sqlreader object. Then ago through each record and update LaborCost colmn using update query.我从 shoporder 表中读取数据到数据 sqlreader object。然后通过每条记录并使用更新查询更新 LaborCost colmn。

private void button1_Click(object sender, EventArgs e)
{
    string ConnectionString=@"Data Source=DESKTOP-KM9K7OP\SQLEXPRESS;Initial Catalog=TheSinkSQLVersion;Integrated Security=True";

    SqlConnection connection1 = new SqlConnection();
    SqlConnection connection2= new SqlConnection();// As suggested by CAIUS JARD
    connection2.ConnectionString = ConnectionString;
    connection1.ConnectionString = ConnectionString;
    connection1.Open();
    connection2.Open();
    SqlCommand command1 = new SqlCommand();
    SqlCommand command2;
    string SqlString = "Select ShopOrderNo, LaborCost, TireRepairCost From shoporder Where TireRepairCost > '0'";
    command1.Connection = connection1;
    command1.CommandText = SqlString;
            
    using (SqlDataReader reader = command1.ExecuteReader())
    {
        while (reader.Read())
        {
            command2 = new SqlCommand();
            command2.Connection = connection2;
            decimal newLaborCost = (decimal)reader["LaborCost"] + (decimal)reader["TireRepairCost"];
            decimal tireRepairCost = 0.0m;//set tire repair cost to zero

            string sqlString2 = "Update shoporder Set LaborCost= @LaborCost, TireRepairCost = @TireRepairCost Where ShopOrderNo ='" + reader["ShopOrderNo"] + "'";
            command2.CommandText = sqlString2;
            SqlParameter param = new SqlParameter("@LaborCost", newLaborCost); command2.Parameters.Add(param);
            param = new SqlParameter("@TireRepairCost", tireRepairCost); command2.Parameters.Add(param);
            command2.ExecuteNonQuery();
            command2.Dispose();
        }//End While
        reader.Close();
    }//end using reader
                
    connection1.Close();
    connection2.Close();            
} //end btnClick
   

As coded, the entire operation can be collapsed to just executing an SQL of:按照编码,整个操作可以折叠为仅执行 SQL:

UPDATE shoporder 
SET LaborCost = LaborCost + TireRepairCost, TireRepairCost = 0 
WHERE TireRepairCost > 0

Minimally that would look like:至少看起来像:

private void button1_Click(object sender, EventArgs e)
{
  using var c = new SqlCommand("UPDATE shoporder SET LaborCost = LaborCost + TireRepairCost, TireRepairCost = 0 WHERE TireRepairCost > 0", ConnectionString);
  c.Connection.Open();
  c.ExecuteNonQuery();
}

Footnote脚注

If you're going to be doing a lot of database work like this, switching to using Dapper will help you out.如果您打算像这样进行大量数据库工作,那么切换到使用 Dapper 将帮助您。 Dapper code would be: Dapper代码将是:

private async void button1_Click(object sender, EventArgs e)
{
  using var c = new SqlConnection(ConnectionString);
  await c.ExecuteAsync("UPDATE shoporder SET LaborCost = LaborCost + TireRepairCost, TireRepairCost = 0 WHERE TireRepairCost > 0");
}

..but the real magic of Dapper is where you want to run DB queries and get objects: ..但 Dapper 的真正魔力在于您想要运行数据库查询并获取对象的地方:

using var c = new SqlConnection(ConnectionString);
var orders = await c.QueryAsync<ShopOrder>("SELECT * FROM shopOrders WHERE TireRepairCost > @cost", new{ cost = 0 }).ToList();

Just those two lines would give you a list of ShopOrder collection objects to do stuff with.仅仅这两行就会给你一个 ShopOrder 集合对象的列表来做一些事情。 Doing it "the long way" would be more like:做“漫长的路”更像是:

using var c = new SqlCommand("SELECT * FROM shopOrders WHERE TireRepairCost > @cost", ConnectionString);
c.Parameters.AddWithValue("@cost", 0); //btw, google 'addwithvalue is evil'
c.Connection.Open();
var r = c.ExecuteReader();
var orders = new List<ShopOrder>();
while(r.Read()){
  orders.Add(new ShopOrder {
    Id = r.GetInteger("Id"),
    LaborCost = r.GetInteger("LaborCost"),
    TireCost = r.GetInteger("TireCost"),
  });
}

Painful..痛苦..

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM