实体框架、事务和存储过程
本文关键字:存储过程 事务 框架 实体 | 更新日期: 2023-09-27 18:07:24
我有一个存储过程,它根据来自另一个表的值将数据写入一个表。因此,它从表中读取开始/结束日期,然后创建大量数据并将其写入单独的表。
所发生的是用户为某事选择开始/结束日期,然后我将开始/结束日期存储到一个表中。然后从EF中调用存储过程,该过程从刚刚更新的表中读取数据,并填充另一个表。
如果进程失败,我想回滚进程写的所有数据,以及表的初始更新。
我认为数据只写入表(初始更新,在EF中完成),当你调用'SaveChanges'。所以我调用它,然后调用这个过程。是否有一种方法可以检测过程是否失败,如果失败,则回滚所有更新(表更新和过程所做的任何事情)?
目前,我的代码看起来像这样,但似乎SaveChanges中的参数是无效的(没有参数),并且'AcceptAllChanges'是无效的:
using (var scope = new TransactionScope())
{
Context.SaveChanges(false);
Context.project_scheduled_event_payments(st.id);
Context.AcceptAllChanges();
}
可以使用事务作用域。您需要添加对System.Transactions.dll
的引用并添加using System.Transactions;
如果您调用SaveChanges()或SaveChanges(true), EF只是假设如果它的工作完成得很好,一切都很好,它会的放弃它一直跟踪的更改,并等待新的更改。
不幸的是,如果在其他地方出了问题事务,因为EF丢弃了它正在跟踪的更改,我们不能恢复。
这就是SaveChanges(false)和AcceptAllChanges()的用武之地。
SaveChanges(false)告诉EF执行必要的数据库命令,但保留更改,以便可以重播必要的。
现在,如果更广泛的事务失败,您可以重试EF特定的另外调用SaveChanges(false)。或者你可以遍历状态管理器以记录失败的内容。
一旦更广泛的事务成功,您只需调用手动的AcceptAllChanges(),以及正在跟踪的更改被丢弃。
using (TransactionScope scope = new TransactionScope())
{
//Do something with context1
//Save Changes but don't discard yet
context1.SaveChanges(false);
//run your secondary procedure, if it succeeds then:
//
//
context1.AcceptAllChanges();
}
edit:好吧,以上将不起作用,因为.SaveChanges(false)
是ObjectContext
方法(也不适合.SaveChanges(SaveOptions)
),我们有DbContext
。我们知道DbContext
是ObjectContext
的包装器,所以我们可以使用IObjectContextAdapter
来访问.SaveChanges(SaveOptions)
方法:
首先我们需要添加using System.Data.Entity.Infrastructure;
,然后:
using (TransactionScope scope = new TransactionScope())
{
// do something with your context
// cast your context to IObjectContextAdapter to get access to the full SaveChanges(SaveOptions) method
IObjectContextAdapter contextAdapter = context;
// .DetectChangesBeforeSave is the equivalent of .SaveChanges(false);
contextAdapter.ObjectContext.SaveChanges(
System.Data.Entity.Core.Objects.SaveOptions.DetectChangesBeforeSave);
//run your secondary procedure, if it succeeds then:
//
//
contextAdapter.ObjectContext.AcceptAllChanges();
scope.Complete();
}