工作单元+实体框架+事务的行为,在异常时没有显式回滚

本文关键字:异常 框架 实体 单元 事务 工作 | 更新日期: 2023-09-27 18:18:09

如果一个事务在using中启动,然后发生异常,但是回滚从未发生,因为没有try - catch回滚,会发生什么?

为了更详细地说明这个问题,请看下面的例子:我们使用工作单元模式来生成业务事务。

工作单元封装在using中。当启动工作单元时,我们可能会启动一个事务(参见下面的示例)。

//Starts a transaction
using (var uow = repositoryFactory.BeginUnitOfWork(true))
{
    //do stuff
    uow.Commit();
}

使用实体框架启动事务:

 CurrentContext.Database.BeginTransaction()

现在的问题是,当一个异常被抛出,而"做东西"的回滚是自动触发的?

存储库工厂按如下方式处置"CurrentContext":

public void Dispose()
{
    if (CurrentContext != null)
    {
        CurrentContext.Dispose();
    }
    CurrentContext = null;
    GC.SuppressFinalize(this);
}

我发现的是,如果与数据库的连接关闭,则打开的事务将被关闭(s.如果您没有在数据库(例如SQL Server)中提交事务会发生什么)。这样做的问题是,当连接关闭时,它会被释放回池(s. https://msdn.microsoft.com/en-us/library/8xx3tyca(v=vs.110).aspx):

)

当连接关闭时,它将被释放回池中到基于其事务上下文的适当细分中。因此,您可以关闭连接而不会产生错误,即使分布式事务仍处于挂起状态。这允许您可以稍后提交或中止分布式事务。

工作单元+实体框架+事务的行为,在异常时没有显式回滚

没有try-catch块,但有try-finally块,即using语句本身,大致相当于以下内容:

var uow = repositoryFactory.BeginUnitOfWork(true);
try
{
    //do stuff
    uow.Commit();
}
finally {
    // pseudo-code
    if (!uow.IsComplete) {
        uow.Rollback();
    }
}

因此,如果发生异常,事务将回滚,即使没有显式的try-catch块在using中。如果没有显式地提交,也会发生同样的情况。