当前位置:  开发笔记 > 编程语言 > 正文

EF6中的嵌套事务行为

如何解决《EF6中的嵌套事务行为》经验,为你挑选了1个好方法。

我目前正在使用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();
        }
    }
}

usr.. 7

在内部事务可以独立提交或回滚的意义上,没有嵌套事务这样的事情.嵌套事务实际上只保留引用计数.在最后一次提交时,我们得到一个物理提交.在第一次回滚时,我们获得了物理回滚.只是确保你知道这一点.

避免使用MSDTC非常重要.无论是with TransactionScope还是with都可以BeginTransaction.使用前者,您需要Open在范围内显式连接,以便EF不会一直打开新连接.

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

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

这非常适合TransactionScope.我认为你的转变BeginTransaction是基于一种误解.也许你可以在评论中澄清一下.

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

在第一段中解释.

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

除了丢失的db.Connection.Open()调用之外,代码看起来很好(如上所述).

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



1> usr..:

在内部事务可以独立提交或回滚的意义上,没有嵌套事务这样的事情.嵌套事务实际上只保留引用计数.在最后一次提交时,我们得到一个物理提交.在第一次回滚时,我们获得了物理回滚.只是确保你知道这一点.

避免使用MSDTC非常重要.无论是with TransactionScope还是with都可以BeginTransaction.使用前者,您需要Open在范围内显式连接,以便EF不会一直打开新连接.

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

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

这非常适合TransactionScope.我认为你的转变BeginTransaction是基于一种误解.也许你可以在评论中澄清一下.

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

在第一段中解释.

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

除了丢失的db.Connection.Open()调用之外,代码看起来很好(如上所述).

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

推荐阅读
sx-March23
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有