SqlDataReader与2个SqlCommand冲突。
SqlDataReader与2个SqlCommand冲突。
我有两个SqlCommand
,我想在同一个方法中同时使用它们,所以我不明白为什么它不起作用。这个方法将根据每个Read()
的ItemId
来同时更新一列。
在SqlDataReader.Read()
期间执行SqlCommand
是否可能?
下面是我得到的异常:
已经存在与此命令关联的打开的 DataReader,必须先关闭它。
我的代码:
private void UpdateStock() { string thisUpdateCommandText = "UPDATE [Item] SET [Stock] += @Quantity WHERE [ItemId] = @ItemId"; string thisSelectCommandText = "SELECT [ItemId], [Quantity] FROM [PackageItem] WHERE [PackageId] = @PackageId"; using (SqlConnection thisSqlConnection = new SqlConnection(theConnectionString)) using (SqlCommand thisSelectSqlCommand = new SqlCommand(thisSelectCommandText, thisSqlConnection)) { thisSqlConnection.Open(); thisSelectSqlCommand.Parameters.Add("@PackageId", SqlDbType.Int).Value = thePackageId; using (SqlDataReader thisSqlDataReader = thisSelectSqlCommand.ExecuteReader()) { while (thisSqlDataReader.Read()) { using (SqlCommand thisUpdateSqlCommand = new SqlCommand(thisUpdateCommandText, thisSqlConnection)) { thisUpdateSqlCommand.Parameters.Add("@ItemId", SqlDbType.Int).Value = thisSqlDataReader.GetInt32(0); thisUpdateSqlCommand.Parameters.Add("@Quantity", SqlDbType.Int).Value = thisSqlDataReader.GetInt32(1); thisUpdateSqlCommand.ExecuteNonQuery(); } } } } }
在使用SqlDataReader时,如果同时进行了两个调用,那么必须为每个调用使用不同的SqlConnection。SqlDataReader在缓冲区中进行读取,这就是为什么它非常快的原因。但另一种方法是将数据保存在DataSet、DataTable或对象列表中,然后调用另一个SqlDataReader,因为您已经将数据保存在对象中并关闭了datareader,所以缓冲区已关闭。使用SqlDataReader会建立一个直接的连接并保持打开状态,直到SqlDataReader关闭,才会将SqlConnection返回给您用于另一个SqlCommand。但在DataSet或DataTable中,缓冲区是打开的并保存数据,然后关闭,这就是为什么它更慢的原因。但每种方法都有其适用情况,您需要学习如何、何时和为什么使用它们。
在使用另一个Command的SqlDataReader时,情况是相同的。一个SqlConnection由SqlDataReader缓冲区保留直到关闭,另一个必须使用另一个SqlConnection,因为第一个被SqlDataReader缓冲区保留。
请注意MARS及其问题:
我建议除非被迫这样做,否则不要使用MARS。
我的建议是,除非被迫,否则不要使用MARS。
SqlDataReader conflicted with 2 SqlCommand错误的出现原因是在同一个SqlConnection中只能打开一个SqlDataReader。只有在第一个SqlDataReader被关闭之后,才能尝试打开另一个SqlDataReader。在SqlDataReader被使用期间,相关的SqlConnection将被占用,直到调用Close方法关闭SqlDataReader。
解决这个问题的方法是寻找其他途径来执行查询操作。一种可能的解决方案是将两个查询包装在一个单独的SQL事务中,并将参数传递给该事务,以便在事务中完成所有操作。这样做有很多好处,除了解决这个问题之外。
需要注意的是,在使用MARS(Multiple Active Result Sets)时要非常小心。在像这样的示例中,使用MARS很可能会导致更多严重的问题。特别是,数据一致性可能会受到影响。