工作单元+实体框架+事务的行为,在异常时没有显式回滚
本文关键字:异常 框架 实体 单元 事务 工作 | 更新日期: 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中。如果没有显式地提交,也会发生同样的情况。