SqlDataReader与2个SqlCommand冲突。

11 浏览
0 Comments

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

0
0 Comments

在使用SqlDataReader时,如果同时进行了两个调用,那么必须为每个调用使用不同的SqlConnection。SqlDataReader在缓冲区中进行读取,这就是为什么它非常快的原因。但另一种方法是将数据保存在DataSet、DataTable或对象列表中,然后调用另一个SqlDataReader,因为您已经将数据保存在对象中并关闭了datareader,所以缓冲区已关闭。使用SqlDataReader会建立一个直接的连接并保持打开状态,直到SqlDataReader关闭,才会将SqlConnection返回给您用于另一个SqlCommand。但在DataSet或DataTable中,缓冲区是打开的并保存数据,然后关闭,这就是为什么它更慢的原因。但每种方法都有其适用情况,您需要学习如何、何时和为什么使用它们。

在使用另一个Command的SqlDataReader时,情况是相同的。一个SqlConnection由SqlDataReader缓冲区保留直到关闭,另一个必须使用另一个SqlConnection,因为第一个被SqlDataReader缓冲区保留。

请注意MARS及其问题:

https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql/enabling-multiple-active-result-sets

我建议除非被迫这样做,否则不要使用MARS。

我的建议是,除非被迫,否则不要使用MARS。

0
0 Comments

SqlDataReader conflicted with 2 SqlCommand错误的出现原因是在同一个SqlConnection中只能打开一个SqlDataReader。只有在第一个SqlDataReader被关闭之后,才能尝试打开另一个SqlDataReader。在SqlDataReader被使用期间,相关的SqlConnection将被占用,直到调用Close方法关闭SqlDataReader。

解决这个问题的方法是寻找其他途径来执行查询操作。一种可能的解决方案是将两个查询包装在一个单独的SQL事务中,并将参数传递给该事务,以便在事务中完成所有操作。这样做有很多好处,除了解决这个问题之外。

需要注意的是,在使用MARS(Multiple Active Result Sets)时要非常小心。在像这样的示例中,使用MARS很可能会导致更多严重的问题。特别是,数据一致性可能会受到影响。

0