如果在foreach循环内部对EF实体进行更改,调用EF SaveChanges()方法和在循环外部调用有没有性能上的优劣差别/技术差异?
如果在foreach循环内部对EF实体进行更改,调用EF SaveChanges()方法和在循环外部调用有没有性能上的优劣差别/技术差异?
是的!
如果你在循环内调用它,EF将为每个实体(每个实体将在自己的单独事务中)将更改写回数据库。
反之,您将进行所有更改,EF将在循环后一次性将它们全部写回(对于所有实体一起使用一个单独的事务)。
作为一般经验法则(在没有实际查看代码的情况下),尽量少地调用.SaveChanges()
。
与每个更改调用50次相比,一次调用50次更改通常更好/更快/更有效。
还有一件事需要说明,如果你的foreach循环遍历了在你的DbContext中处于活动状态的EntitySet,那么你将会收到一个System.Data.SqlClient.SqlException异常:另一个线程正在该会话中运行。
这是因为foreach实际上在另一个线程中运行,而事务不允许完成这种操作。
除了以上提到的尽量减少事务次数的建议外,还需注意这个问题。
假设你有一个名为db的context并执行以下操作:
var groups = from i in db.items select i.GroupNumber;
foreach( var grp in groups)
{
//... do something
db.SaveChanges();
}
这将抛出异常
避免这种情况的一种解决方案(如果适用!)是通过将它们带入对象空间来实现“实体组”的“实质化”,方法是将第一行更改为:
var groups = (from i in db.items select i.GroupNumber).ToList();
这将允许您在foreach中保存(如果需要)
在循环外只会创建一个事务来更新数据库,而在循环内每次迭代都会创建一个事务。因为EF使用了工作单元模式,它将所有的更改保存在内存中,在SaveChanges方法中将所有更改保存到数据库中。
性能会有所不同,在循环内部,您将在每次迭代中调用数据库。在循环外部,您将只调用一次数据库。这可能会对性能产生巨大影响,具体取决于您有多少次迭代。
.SaveChanges()
操作都会失败,并且不会将任何内容存储到数据库中。 - marc_s