c# - 实体框架 - 混合存储过程和实体的回滚
问题描述
我需要调用一些存储过程(数据插入)并将实体值更新到数据库。
我希望这些操作是原子的,所以如果发生错误,它们都会回滚。
在我的代码中,如果我强制异常来观察回滚的行为,我的实体更改正在回滚,但我的存储过程更改不会回滚。
查看工作单元的实现,它只是查看_context.ChangeTracker.Entries()
- 我假设完全忽略任何存储过程更改?
当我将工作单元实施更改为使用
new System.Transactions.TransactionScope()
回滚按预期工作。
我应该使用new System.Transactions.TransactionScope()
吗?有什么陷阱吗?
代码
...
using (var scope = _unitOfWork.Begin())
{
try
{
var outcome = _context.Database.ExecuteSqlCommand("SOME EXEC COMMAND", parameters);
throw new Exception("Something happened");
scope.Commit(); // Never gets called because of Exception
}
catch (Exception e)
{
scope.Rollback();
}
}
工作单位:
public class UnitOfWork : IUnitOfWork, ITransaction
{
private readonly DbContext _context;
private bool _committed;
public UnitOfWork(DbContext context)
{
_context = context;
}
public ITransaction Begin()
{
_committed = false;
return this;
}
public void Commit()
{
_context.SaveChanges();
_committed = true;
}
public void Rollback()
{
foreach (var entry in _context.ChangeTracker.Entries())
{
switch (entry.State)
{
case EntityState.Modified:
entry.State = EntityState.Unchanged;
break;
case EntityState.Added:
entry.State = EntityState.Detached;
break;
case EntityState.Deleted:
entry.Reload();
break;
case EntityState.Detached:
break;
case EntityState.Unchanged:
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}
public void Dispose(bool disposing)
{
if (!disposing)
return;
if (!_committed)
{
Rollback();
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
解决方案
是的——当然,更改跟踪器只能跟踪您通过课程更改/修改/添加的任何内容DbContext
。
运行存储过程超出了 EF Change Tracker 的范围 - 因此,如果您将“回滚”简单地基于 Change Tracker 中的内容,您将无法正确处理存储过程所做的任何事情。
使用TransactionScope
是根本不同的 - 这是所有数据库操作的“保护伞” - 包括正在执行的任何存储过程 - 因为它基本上是在数据库级别上。因此,基于事务范围的回滚将回滚所有数据库操作——无论是通过 EF 处理DbContext
,还是通过其他方式处理。
推荐阅读
- javascript - jQuery post 不适用于 safari 但适用于 chrome
- android - 如何在手机上安装 React Native 应用程序
- javascript - 如何使用 Leaflet CoordsToLatLngs 在地图上绘制折线?
- android - Android GrantPermissionRule 不适用于 api-27
- spring-boot - 当有 3 个数据源而没有任何 @Primary 时,Spring 批量设置数据源
- node.js - 如何配置 express 以使用 dotnet core localhost SSL 证书?
- r - 不同时间点的固定效应
- html - 关于 CSS - 使用 CSS 位置属性但它不起作用
- python - Manim 中的余弦函数图错误
- javascript - AngularJS 中的自定义过滤器