在 foreach 循环中提交事务
Commit transaction in foreach loop
我在 foreach 循环中向 DB 添加一个条目并使用事务。但我收到此错误:
The connection is already in a transaction and cannot participate in another transaction.
更新 :
var user = await CurrentUser;
if (user.IsNotNull())
{
using (var transaction = _context.Database.BeginTransaction())
{
try
{
var reports = new List<ReportEntity>();
foreach (var model in modelList)
{
reports.Add(new ReportEntity
{
Id = Guid.NewGuid(),
UserId = user.Id,,
ReportTypeId = ReportTypeId
});
}
await _context.tbl_Reports.AddRangeAsync(reports);
await _context.SaveChangesAsync();
await transaction.CommitAsync();
resp.Status = true;
}
catch (Exception e)
{
resp.ErrorMessage = e.Message;
await transaction.RollbackAsync();
}
} //End of transaction
}
}
else
{
resp.ErrorMessage = "User not found";
}
我正在根据 POST 中的对象数组循环添加记录。我什么时候提交交易才不会收到这个错误?
看起来您没有关闭交易以防 user
为空。这是您的代码中实际发生的情况:
- 你调用了调用
_context.Database.BeginTransaction()
的方法
- 为连接打开一个事务
user
为null,导致不调用CommitAsync
或RollbackAsync
- 即使在方法执行完成后事务仍在使用中,它在连接上打开
- 您再次调用该方法,可能会创建一个新的 EF 上下文,但是,EF 上下文不会每次都创建一个新连接,它会重新使用连接池中现有的连接
- EF 上下文选择在第 2 步中使用的连接,并且事务已经打开
- 您尝试在已打开事务的连接上打开另一个事务,但出现异常(即使这次
user
不为空)
我想应该是这样的。您可以尝试 commit/rollback 事务,即使数据库中没有任何更改,这应该可以解决问题。
关于 SqlConnection.BeginTransaction 的文档说:
You must explicitly commit or roll back the transaction using the Commit or Rollback method.
更新
如果上面提到的没有帮助,还有其他的事情应该考虑和检查:
- 有第三方库与数据库交互并打开事务。有时他们帮助使用 EF 并提供
BatchInsert
或 BatchUpdate
等功能。它们可以在您的代码中的某处调用。
- 同时访问单个 EF 上下文,例如,如果它存储在静态字段中并且多个线程试图同时使用它。
- 外部代码可以在调用您的代码之前创建交易,您的代码也可以在嵌套调用中创建交易。
注意所有用到异常的EF上下文的地方。
我在 foreach 循环中向 DB 添加一个条目并使用事务。但我收到此错误:
The connection is already in a transaction and cannot participate in another transaction.
更新 :
var user = await CurrentUser;
if (user.IsNotNull())
{
using (var transaction = _context.Database.BeginTransaction())
{
try
{
var reports = new List<ReportEntity>();
foreach (var model in modelList)
{
reports.Add(new ReportEntity
{
Id = Guid.NewGuid(),
UserId = user.Id,,
ReportTypeId = ReportTypeId
});
}
await _context.tbl_Reports.AddRangeAsync(reports);
await _context.SaveChangesAsync();
await transaction.CommitAsync();
resp.Status = true;
}
catch (Exception e)
{
resp.ErrorMessage = e.Message;
await transaction.RollbackAsync();
}
} //End of transaction
}
}
else
{
resp.ErrorMessage = "User not found";
}
我正在根据 POST 中的对象数组循环添加记录。我什么时候提交交易才不会收到这个错误?
看起来您没有关闭交易以防 user
为空。这是您的代码中实际发生的情况:
- 你调用了调用
_context.Database.BeginTransaction()
的方法 - 为连接打开一个事务
user
为null,导致不调用CommitAsync
或RollbackAsync
- 即使在方法执行完成后事务仍在使用中,它在连接上打开
- 您再次调用该方法,可能会创建一个新的 EF 上下文,但是,EF 上下文不会每次都创建一个新连接,它会重新使用连接池中现有的连接
- EF 上下文选择在第 2 步中使用的连接,并且事务已经打开
- 您尝试在已打开事务的连接上打开另一个事务,但出现异常(即使这次
user
不为空)
我想应该是这样的。您可以尝试 commit/rollback 事务,即使数据库中没有任何更改,这应该可以解决问题。
关于 SqlConnection.BeginTransaction 的文档说:
You must explicitly commit or roll back the transaction using the Commit or Rollback method.
更新 如果上面提到的没有帮助,还有其他的事情应该考虑和检查:
- 有第三方库与数据库交互并打开事务。有时他们帮助使用 EF 并提供
BatchInsert
或BatchUpdate
等功能。它们可以在您的代码中的某处调用。 - 同时访问单个 EF 上下文,例如,如果它存储在静态字段中并且多个线程试图同时使用它。
- 外部代码可以在调用您的代码之前创建交易,您的代码也可以在嵌套调用中创建交易。
注意所有用到异常的EF上下文的地方。