【问题标题】:UnitOfWork with Entity Framework is not committing the transaction带有实体框架的 UnitOfWork 未提交事务
【发布时间】:2016-01-01 19:43:38
【问题描述】:

我有一个 UoW 类,它的启动和提交如下

public class uow
{
    private IDBcontext mydbcontext;
    TransactionScope trans = null;

    public uow(IDBConext mydbcontext)
    {
        this.mydbcontext = mydbcontext;
    }

    public void starttran()
    {
       if (trans == null)
           trans = new TransactionScope(TransactionScopeAsyncFlowOption.enabled);
    }

    public async task Commit()
    {
       var mydb = mydbcontext as IObjectContextAdapter;
       if (mydb != null)
          await mydb.ObjextContext.SaveChangesAsync(SaveOptions.DetectChangesBeforeSave);

       if (trans!=null)
       {
           trans.Complete();
           trans = new TransactionScope();
       }

       mydb.ObjectContext.AcceptAllChanges();
   }
}

现在在我的实现中,我将 2 条记录插入到 2 个不同的表中并取回键值。然后我使用这两个键再次插入到第三个表中。

如果第二次或第三次插入失败,我需要能够回滚第一次或前两次插入(插入应该全部成功或全部失败)。

Table1 tab1 = new Table1();
Table2 tab2 = new Table2();
Table3 tab3 = new Table3();

UOW uw = new UOW(mydbcontext);
uw.Starttran();

tab1.createdby = "user1";
tab1.name = "name";

tab1 = mydbcontext.Table1.Add(tab1);
await mydbcontext.SaveChangesAsync();

tab2.createdby = "user1";
tab2.name = "name";

tab2 = mydbcontext.Table2.Add(tab2);
await mydbcontext.SaveChangesAsync();

tab3.table1Id = tab1.Id;
tab3.table2Id = tab2.Id;

tab3 = mydbcontext.Table3.Add(tab3);
await mydbcontext.SaveChangesAsync();

if(tab3.Id > 0)
  await uow.Commit();
else
  await uow.RollBack();

我的问题是:事务没有提交。正如我在调试时看到的,tab3.Id 值创建得很好并且它是有效的。但是当我查询我的 SQL Server 表时,它显示一个锁并且不返回任何查询结果。当我手动关闭调试会话时,没有锁定 - 但新记录不存在/未插入。

我在这里做错了什么?在此处阅读 uow 上的多个主题,但找不到答案..

【问题讨论】:

  • 你确定这段代码正在编译吗?您正在调用的某些方法不存在
  • 抱歉 - 我没有写回滚的正文,因为它在这里无关紧要......但我确实有......
  • 我实际上确实使用了 await uow.Commit()..当我在这里输入时错过了..
  • 离题,但相关:您只使用 UoW 作为 TransactionScope 的包装。你为什么不按预期使用它?另外(再次回到主题),如果您设置对象引用而不是外键值,则不需要所有这些 SaveChangesAsync 调用。一个就可以了,而且您不必完全管理自己的交易。这可能足以让它正确。
  • 您是否尝试设置对象引用而不是 FK 值?

标签: c# sql-server async-await entity-framework-6 unit-of-work


【解决方案1】:

commit 方法返回一个可等待的Task,因此由于没有等待调用,因此程序可能会继续运行,甚至在调用完成之前完成。在你实施的最后一部分,你应该这样做:

if(tab3.Id > 0)
  await uow.Commit();
else
  await uow.RollBack();  // Assuming that this one is also an async method

一个好的做法是将前缀 Async 添加到支持 async-await 的方法中。

另外,但与问题无关,当您提交事务时,为什么要创建新的事务范围?这似乎没有必要,并且根据工作单元模式的定义,一旦提交更改,就不应重新使用工作单元。

if (trans!=null)
{
  trans.Complete();
  trans = new TransactionScope(); // ???
}

【讨论】:

  • await 不执行任务。如果等待者未完成,它只会将控制权交还给调用者。
  • 我实际上确实使用了 await uow.Commit() ..它不起作用..我在这里输入时错过了它..我可以更新我的帖子以反映它吗?
  • 是的!这是一个很好的指针 Paulo.. 我该怎么做才能在这里执行它!嗯..让我试试这个提示。
  • 我一定是在这里遗漏了一些东西......无法让它工作!
  • 看到我提交的签名是 Async Task Commit()...它与 void 不同,对吧.. 我认为这就是问题所在..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多