背景
我有一些代码可以打开一个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
}
}
出列方法代码
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;
}
}
获取路径代码
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 "";
}
}
保存代码
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();
}
}
问题
调用transaction.Commit()时,出现以下错误:
无法执行事务操作,因为存在处理此事务的待处理请求。
我做错了什么?
编辑:快速编辑,说我已经在SO上阅读了有关此问题的其他问题,但无法找到与ADO.net相关的任何问题
答案 0 :(得分:19)
之前我遇到过这个问题,问题是读者需要关闭。 试试这个:
tar -xvf spark-1.4.1.tgz
sbt/sbt assembly
答案 1 :(得分:1)
当我忘记对正在执行DB调用的异步方法使用await时,我遇到了这个问题-因为事务在尝试处理所有事务之前没有等待查询完成,所以在事务运行时正在断开连接
答案 2 :(得分:0)
我们遇到了这个问题,虽然接受的答案可能会奏效,但这并不是最正确的做法——但是,它确实为我们提供了关于我们做错了什么的线索。
在我们的例子中,需要读取更多数据。这是问题的简化版本(使用 Dapper):
public Foo GetFooById(int fooId, IDbTransaction transaction = null) {
var sql = @"
SELECT * FROM dbo.Foo WHERE FooID = @FooID;
SELECT * FROM dbo.FooBar WHERE FooID = @FooID;
SELECT * FROM dbo.FooBaz WHERE FooID = @FooID;
";
using var data = await _connection.QueryMultipleAsync(sql, new { fooId }, transaction);
var foo = data.ReadSingle<Foo>();
foo.Bars = data.Read<Bar>();
// Oops, didn't read FooBar.
return foo;
}
即使 data
被释放,它也会在事务上留下一个“待处理的请求”,然后在调用 transaction.Commit()
时它会爆炸。
解决方案是从 FooBaz
中读取 data
条记录,或者去掉未读取的 SELECT
。