2016-05-13 122 views
3

我有一个命令服务类,它利用工作单元模式,通过实体框架用各种方法更新数据库(本例中为SQL Azure)。EF6嵌套事务

命令服务通过引用一个dbcontext实例来实例化,该实例的生命周期由我选择的DI框架管理。

一些命令服务类的方法包装的多个更新到数据库的事务中,例如:

public void UpdateStuff(someEntity) 
{ 
    using(var tx = _db.Database.BeginTransaction()) 
    { 
     //Some updates to db 
     _db.SaveChanges(); 
     //Some other updates to db 
     _db.SaveChanges(); 
     tx.Commit(); 
    } 
} 

现在,一些方法调用从他们的交易中的命令类的其他方法,例如:

public void UpdateWithSomeCascadingStuff(someOtherEntity) 
{ 
    using(var tx = _db.Database.BeginTransaction()) 
    { 
     //Some updates to db 
     _db.SaveChanges(); 

     //Some other cascading logic and updates to db 
     var relatedEntityToUpdate = _query.GetSomeEntityToUpdate(someOtherEntity); 
     UpdateStuff(relatedEntityToUpdate); 
     _db.SaveChanges(); 
     tx.Commit(); 
    } 
} 

显然,通过这样做,我为同一个DbContext实例嵌套了EF事务。

这是否被支持,它会导致任何麻烦?我可以采取其他方法吗?

更新: 我使用EF6代码第一次

回答

1

的EntityFramework的DBContexts本身同时实现的UnitOfWork和信息库模式。

EF6中的上下文还自动将事务中的所有提交包装在自身中(如果它不是其中的一部分)。

所以,不,你不应该在多个工作单元之间共享上下文。他们应该各自拥有自己的。

UPDATE

如果你试图在你得到同样的DbContext开始重复的事务:

An unhandled exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll 

Additional information: The connection is already in a transaction and cannot participate in another transaction. EntityClient does not support parallel transactions. 

所以,不,你不能做你所要求的。

+0

谢谢,但这不能回答我的问题。 –

+1

EF隐藏在客户端代码的接口后面(因为我需要能够轻松刷出存储机制而不影响客户端代码),并且还有一些CQRS正在进行。因此,我必须“包装”其UOW实施。如何,为什么和正确这是一个太长的讨论。我知道EF在SaveChanges之前在单个事务中包装指令。在我的情况下,我有多个SaveChanges调用,需要在单个事务中进行包装。再一次 - 不是在这里捍卫设计 - 我只是想知道我是否可以在另一个嵌套EF6交易。 –

+1

我扩大了我的答案。希望有助于更好地回答你的问题 –