实体框架-在没有事务的情况下强制提交
本文关键字:情况下 提交 事务 框架 实体 | 更新日期: 2023-09-27 17:58:26
我有一个循环,看起来有点像:
CountsToReport = rep.Counts_Get().Where(x => x.Status == "Completed");
foreach (var count in CountsToReport.ToList())
{
//do some stuff
//send an email
count.Status = "Reported";
rep.SaveChanges();
}
其中"rep"是围绕EF上下文的存储库包装器。
当这种情况运行时,不幸的电子邮件收件人会收到大量垃圾邮件,因为SaveChanges调用实际上并没有提交更改,所以循环不断获得相同的计数,发送电子邮件,并将其标记为"已报告",但实际上并没有保存更改。
如果停止循环并重新启动代码,则更改将成功保存。您可以通过逐步执行代码来确认这种情况:C#中的EF对象会更改其状态,但SQL中的底层数据不会更改。
我推测这是因为SaveChanges实际上并没有提交事务——它只是将数据标记为已更改,为事务结束做好准备。但是,我们没有在数据库中的任何其他地方使用事务,并且为这个用例更改存储库会有点麻烦。
有没有其他方法可以迫使EF做出这一改变,逃离我无尽的厄运循环?还是我弄错了原因?
编辑:把这个放在存储库中,并调用它而不是SaveChanges他的修复程序:
public void SaveWithTransaction()
{
using (var transaction = new System.Transactions.TransactionScope())
{
db.SaveChanges();
transaction.Complete();
}
}
但它看起来很丑陋。仍然有兴趣知道是否还有其他办法。
编辑:这是骗人的。看起来这又是一个旧的添加/修改问题。将对象标记为已修改似乎有帮助。
CountsToReport中的实体很可能与上下文分离。因此,ChangeTracker不仅没有看到对Count进行任何更改,而且对实体一无所知。
解决问题:
- 遍历CountsToReport的集合
- 将每个实体附加回上下文,类似于
db.Counts.Attach(count)
- 修改计数。状态和调用数据库。SaveChanges()
像这样:
foreach (var count in CountsToReport.ToList())
{
//do some stuff
//send an email
rep.Counts.Attach(count);
count.Status = "Reported";
rep.SaveChanges();
}
有关实体状态以及如何处理这些状态的更多信息,请查看以下链接:http://msdn.microsoft.com/en-us/data/jj592676.aspx