繁体   English   中英

EF6中的嵌套事务行为

[英]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非常重要。 这可以通过TransactionScopeBeginTransaction 使用前者,您需要在范围内显式Open连接,以便EF不会一直打开新连接。

正如你在这个问题中所读到的那样,这是EF的一个缺陷(L2S没有)。 请花点时间对问题发表评论,以确保团队了解客户遇到此问题。

特别是在我想要使用环境事务而不是创建新事务的场景中。

这对TransactionScope来说非常完美。 我认为你切换到BeginTransaction是基于一个误解。 也许你可以在评论中澄清一下。

嵌套在另一个事务中时确认Database.BeginTransaction()的行为

在第一段中解释。

有关我的DAL的其他信息:基于CQS模式,我倾向于在命令或查询处理程序中封装Db相关代码,因此这种嵌套如何发生的简化/设计示例将是:

代码看起来很好,除了缺少db.Connection.Open()调用(如上所述)。

此模式将支持在同一事务中执行多个查询和命令。 只需在其周围包裹另一个范围。 确保不要两次打开连接,例如在采取措施之前检查conn.State

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM