无法执行事务操作,因为有待处理的请求正在运行

Jay*_*Jay 15 c# ado.net transactions sqltransaction

背景

我有一些代码打开一个SQL连接,开始一个事务并在数据库上执行一些操作.此代码从DB(dequeue)创建一个对象,获取一些值并将其保存回来.整个操作需要在交易中进行.所有代码在没有事务的情况下完美运行.

using (var connection = new SqlConnection(connectionString))
{
    connection.Open();
    var transaction = connection.BeginTransaction();
    try
    {                       
        var myObject = foo.Dequeue(connection, transaction);

        var url = myObj.GetFilePathUri(connection, transaction);

        //some other code that sets object values

        myObj.SaveMessage(connection, transaction);
        transaction.Commit(); //error here
    }
    catch(Exception ex)
    {                    
        transaction.Rollback();
        //logging                
    }
    finally
    {
        //cleanup code
    }
}
Run Code Online (Sandbox Code Playgroud)

出列方法代码

public foo Dequeue(SqlConnection connection, SqlTransaction transaction)
{
    using (var command = new SqlCommand(DEQUEUE_SPROC, connection) {CommandType = CommandType.StoredProcedure, Transaction = transaction})
    {
        var reader = command.ExecuteReader();
        if (reader.HasRows)
        {
            reader.Read();
            ID = (Guid) reader["ID"];
            Name = reader["Name"].ToString();
            return this;
        }
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

获取路径代码

public string GetFilePathUri(SqlConnection connection, SqlTransaction transaction)
{
    using (var command = new SqlCommand(FILEPATH_SPROC, connection) {CommandType = CommandType.StoredProcedure, Transaction = transaction})
    {
        var reader = command.ExecuteReader();
        if (reader.HasRows)
        {
            reader.Read();
            return reader["Path"].ToString();
        }
        return "";
    }
}
Run Code Online (Sandbox Code Playgroud)

保存代码

public void SaveMessage(SqlConnection connection, SqlTransaction transaction)
{
    using (var command = new SqlCommand(SAVE_SPROC, connection) {CommandType = CommandType.StoredProcedure, Transaction = transaction})
    {
        command.Parameters.Add("@ID", SqlDbType.UniqueIdentifier).Value = ID;
        command.Parameters.Add("@Name", SqlDbType.VarChar).Value = Name;
        //other object params here
        command.ExecuteNonQuery();
    }
}
Run Code Online (Sandbox Code Playgroud)

问题

当调用transaction.Commit()时,我收到以下错误:

无法执行事务操作,因为存在处理此事务的待处理请求.

我究竟做错了什么?

编辑:快速编辑说我已经在SO上阅读了有关此问题的其他问题,但找不到任何与ADO.net相关的问题

Ern*_*est 21

我之前遇到过这个问题,问题是读者需要关闭.试试这个:

public foo Dequeue(SqlConnection connection, SqlTransaction transaction)
{
    using (var command = new SqlCommand(DEQUEUE_SPROC, connection) {CommandType = CommandType.StoredProcedure, Transaction = transaction})
    {
        var reader = command.ExecuteReader();
        if (reader.HasRows)
        {
            reader.Read();
            ID = (Guid) reader["ID"];
            Name = reader["Name"].ToString();
            reader.Close();//Closing the reader
            return this;
        }
        return null;
    }
}


public string GetFilePathUri(SqlConnection connection, SqlTransaction    transaction)
{
    string filePathUri = "";
    using (var command = new SqlCommand(FILEPATH_SPROC, connection) {CommandType = CommandType.StoredProcedure, Transaction = transaction})
    {
        var reader = command.ExecuteReader();
        if (reader.HasRows)
        {
            reader.Read();
            filePathUri = reader["Path"].ToString();
        }
        reader.Close();//Closing the reader
    }
    return filePathUri;
}
Run Code Online (Sandbox Code Playgroud)

  • 不客气 :)。问题是我们通常认为当我们使用“using”时,阅读器将关闭,但使用事务时,它不会关闭,直到您调用 Close() 方法。 (2认同)
  • 阅读器也是`IDisposable`;最佳实践是将其使用包装在一个 `using` 块中。然后异常也会正确关闭它。 (2认同)

NYC*_*Net 12

当我忘记在执行数据库调用的异步方法上使用等待时,我遇到了这个问题 - 在事务运行时连接被释放,因为程序在尝试释放所有内容之前没有等待查询完成。