[英]Nested Transaction Behavior in EF6
我目前正在使用TransactionScope来管理我的数据层中的事务,但我一直遇到嵌套事务和异步的问题,在嵌套事务期间连接似乎关闭或者事务被提升为MSDTC。 我没有找到确切的问题,但在阅读之后看起来这个场景并没有得到特别好的支持,我应该使用Database.BeginTransaction()代替。
我的问题是我无法找到有关Database.BeginTransaction()如何与嵌套事务一起工作的信息,特别是在我想要使用环境事务而不是创建新事务的场景中。 我怀疑它并不打算以这种方式工作,如果我想管理嵌套事务,我应该抽象出事务管理来给我更多控制权。
我不想添加不必要的抽象层,我想知道是否有人有这方面的经验,并且可以在嵌套在另一个事务中时确认Database.BeginTransaction()的行为?
有关我的DAL的其他信息:基于CQS模式,我倾向于在命令或查询处理程序中封装Db相关代码,因此这种嵌套如何发生的简化/设计示例将是:
public class AddBlogPostHandler
{
private readonly MyDbContext _myDbContext;
public AddBlogPostHandler(MyDbContext myDbContext)
{
_myDbContext = myDbContext;
}
public async Task ExecuteAsync(AddBlogPostCommand command)
{
using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
// .. code to create and add a draft blog post to the context
await _myDbContext.SaveChangesAsync();
var publishBlogPostCommand = new PublishBlogPostCommand();
// ..set some variables on the PublishBlogPostCommand
await PublishBlogPostAsync(command);
scope.Complete();
}
}
}
public class PublishBlogPostHandler
{
private readonly MyDbContext _myDbContext;
public PublishBlogPostHandler(MyDbContext myDbContext)
{
_myDbContext = myDbContext;
}
public async Task ExecuteAsync(PublishBlogPostCommand command)
{
using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
// .. some code to do one set of update
await _myDbContext.SaveChangesAsync();
// .. some other db updates that need to be run separately
await _myDbContext.SaveChangesAsync();
scope.Complete();
}
}
}
在内部事务可以独立提交或回滚的意义上,没有嵌套事务这样的事情。 嵌套事务实际上只保留引用计数。 在最后一次提交时,我们得到一个物理提交。 在第一次回滚时,我们获得了物理回滚。 只是确保你知道这一点。
避免使用MSDTC非常重要。 这可以通过TransactionScope
和BeginTransaction
。 使用前者,您需要在范围内显式Open
连接,以便EF不会一直打开新连接。
正如你在这个问题中所读到的那样,这是EF的一个缺陷(L2S没有)。 请花点时间对问题发表评论,以确保团队了解客户遇到此问题。
特别是在我想要使用环境事务而不是创建新事务的场景中。
这对TransactionScope
来说非常完美。 我认为你切换到BeginTransaction
是基于一个误解。 也许你可以在评论中澄清一下。
嵌套在另一个事务中时确认Database.BeginTransaction()的行为
在第一段中解释。
有关我的DAL的其他信息:基于CQS模式,我倾向于在命令或查询处理程序中封装Db相关代码,因此这种嵌套如何发生的简化/设计示例将是:
代码看起来很好,除了缺少db.Connection.Open()
调用(如上所述)。
此模式将支持在同一事务中执行多个查询和命令。 只需在其周围包裹另一个范围。 确保不要两次打开连接,例如在采取措施之前检查conn.State
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.