实体框架中跨多个上下文的单个事务
本文关键字:上下文 单个 事务 框架 实体 | 更新日期: 2023-09-27 18:17:54
我们有一个场景,在单个事务中保存来自两个上下文的两个实体。
step1 - SetTransaction(firstContext, true);
步骤2 -使用firstContext保存第一个实体。
step3 - SetTransaction(secondContext, false);
步骤4 -使用secondContext保存第二个实体
步骤5 -最后提交事务。
void function SetTransaction(context, startNewTransaction)
{
var currentContext = firstContext;
if (startNewTransaction)
{
var connection = currentContext.GetConnection();
connection.Open();
this.dbTransaction = connection.BeginTransaction();
}
if (this.dbTransaction != null)
{
currentContext.UseTransaction(dbTransaction);
}
}
在执行步骤3时,currentContext.UseTransaction(dbTransaction);line抛出异常为"传入的事务与当前连接不关联"。"
请建议如何解决。
Venkat .
使用TransactionScope
。EF将自动在一个正在运行的事务范围中登记。
它将要求你的连接字符串相同。
using (var scope = new TransactionScope()) {
// Save entity in context A
using (var contextA = new ContextA()) {
contextA.Save(...);
contextA.SaveChanges;
}
// Save entity in context B
using (var contextB = new ContextB()) {
contextB.Save(...);
contextB.SaveChanges;
}
// Commit tx-scope
scope.Complete();
}
从EF 6开始不建议使用TransactionScope。所以使用:
using (var conn = new SqlConnection("..."))
{
conn.Open();
using (var sqlTxn = conn.BeginTransaction(System.Data.IsolationLevel.ReadCommitted))
{
try
{
using (var contextA = new ContextA(conn, contextOwnsConnection: false))
{
contextA.Database.UseTransaction(sqlTxn);
contextA.Save(...);
contextA.SaveChanges();
}
using (var contextB = new ContextB(conn, contextOwnsConnection: false))
{
contextB.Database.UseTransaction(sqlTxn);
contextB.Save(...);
contextB.SaveChanges();
}
sqlTxn.Commit();
}
catch (Exception)
{
sqlTxn.Rollback();
}
}
}
}
编辑:如果dbContext没有必需的构造函数,可以添加另一个构造函数,如下所示:
public ContextA(): base("name=ConnectionString")
{
}
public ContextA(DbConnection connection) : base(connection, false)
{
}