C# 实体框架-混合存储过程和实体的回滚
我需要调用一些存储过程(数据插入)并将实体值更新到数据库中 我希望这些操作是原子的,所以如果发生错误,它们都会回滚 在我的代码中,如果我强制一个异常来观察回滚行为,我的实体更改将回滚,但存储过程更改不会回滚 查看工作单元的实现,它只是查看C# 实体框架-混合存储过程和实体的回滚,c#,entity-framework,transactions,C#,Entity Framework,Transactions,我需要调用一些存储过程(数据插入)并将实体值更新到数据库中 我希望这些操作是原子的,所以如果发生错误,它们都会回滚 在我的代码中,如果我强制一个异常来观察回滚行为,我的实体更改将回滚,但存储过程更改不会回滚 查看工作单元的实现,它只是查看\u context.ChangeTracker.Entries()——我假设完全忽略任何存储过程更改 当我将工作单元的实现更改为使用 new System.Transactions.TransactionScope() 回滚按预期工作 我是否应该使用新的Sy
\u context.ChangeTracker.Entries()
——我假设完全忽略任何存储过程更改
当我将工作单元的实现更改为使用
new System.Transactions.TransactionScope()
回滚按预期工作
我是否应该使用新的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
有着根本的不同——这是所有数据库操作(包括正在执行的任何存储过程)的“保护伞”,因为它基本上在数据库级别。因此,基于事务范围的回滚将回滚所有数据库操作—无论是通过EFDbContext处理还是通过其他方式处理。在混合使用存储过程和实体框架实体时,这是推荐的方法吗?我可能会说“你不知道你不知道什么”@SebastianPatten:因为执行存储过程发生在EF的“背后”——那么是的,如果你想确保EF操作和存储过程执行的完整性和一致性,那么就我所知,这是推荐的最佳实践,由于它在ADO.NET/SQL Server级别工作,并处理这两种操作,非常感谢您的及时回复