如何解决 "there is already an open data reader with this command" 错误?
How to solve "there is already an open data reader with this command" error?
我的代码是这样的
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
错误发生在command2.ExecuteNonQuery()。
有办法解决这个问题吗?
我对这两个命令使用相同的连接。
编辑,完整代码如下。我从 shoporder table 读取数据到数据 sqlreader 对象。然后通过每条记录并使用更新查询更新 LaborCost 列。
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
按照编码,整个操作可以折叠为仅执行 SQL of:
UPDATE shoporder
SET LaborCost = LaborCost + TireRepairCost, TireRepairCost = 0
WHERE TireRepairCost > 0
至少看起来像:
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();
}
脚注
如果您要像这样进行大量数据库工作,切换到使用 Dapper 将帮助您。 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");
}
..但 Dapper 的真正魔力在于您想要 运行 数据库查询和获取对象的地方:
using var c = new SqlConnection(ConnectionString);
var orders = await c.QueryAsync<ShopOrder>("SELECT * FROM shopOrders WHERE TireRepairCost > @cost", new{ cost = 0 }).ToList();
仅仅这两行就会给你一个 ShopOrder 集合对象的列表来处理事情。做“长路”更像是:
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"),
});
}
痛苦..
我的代码是这样的
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
错误发生在command2.ExecuteNonQuery()。
有办法解决这个问题吗?
我对这两个命令使用相同的连接。
编辑,完整代码如下。我从 shoporder table 读取数据到数据 sqlreader 对象。然后通过每条记录并使用更新查询更新 LaborCost 列。
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
按照编码,整个操作可以折叠为仅执行 SQL of:
UPDATE shoporder
SET LaborCost = LaborCost + TireRepairCost, TireRepairCost = 0
WHERE TireRepairCost > 0
至少看起来像:
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();
}
脚注
如果您要像这样进行大量数据库工作,切换到使用 Dapper 将帮助您。 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");
}
..但 Dapper 的真正魔力在于您想要 运行 数据库查询和获取对象的地方:
using var c = new SqlConnection(ConnectionString);
var orders = await c.QueryAsync<ShopOrder>("SELECT * FROM shopOrders WHERE TireRepairCost > @cost", new{ cost = 0 }).ToList();
仅仅这两行就会给你一个 ShopOrder 集合对象的列表来处理事情。做“长路”更像是:
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"),
});
}
痛苦..