在.NET中使用Entity Framework我想循环遍历从数据库返回的项目列表并进行更新。
var qry = (from c in DBEntities.Customer select c);
foreach (Object item in qry)
{
item.FirstName = ....
... etc, other code here
DBEntities.SaveChanges();
}
根据:http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/thread/8a337036-d288-48d4-80d4-89e5a51eddd9?ppud=4 S Hargroves建议转换为IList,这就是解决方案。
没试过,我相信它会起作用,但即使它有效,我想知道为什么我不能在循环期间更新项目?这是在我的本地开发环境中发生的,没有其他用户访问数据库。
谢谢...
答案 0 :(得分:11)
在查询中使用SaveChanges更新数据库时,查询无效。您执行的更新可能已更改结果集。
通过使用ToList
,您将触发查询的执行并将数据库中的所有结果带入内存。您的内存列表现在已经具体,不再关注查询了。
因为对象查询使用IEnumerable
,所以不能在foreach中修改列表。
我也相信这段代码会因同样的基本原因而失败:
List<int> numbers = new List<int>() { 1,2,3,4,5,6};
foreach(var num in numbers)
numbers.Remove(num); //Invalidates the Enumerator being used in the foreach
答案 1 :(得分:3)
我同意将var列入清单。 然后在您的foreach中,而不是在qry中使用Object项,请在qry中使用Customer customer。在那种情况下,您实际上是在处理客户对象而不仅仅是对象。在大多数情况下,您不希望在foreach中调用SaveChanges(),因为每次执行时它都会在服务器上执行update命令。如果你在foreach之后执行它,它将对数据库进行一批调用并执行更好的操作。
我建议的伪代码看起来像
var customers = (from c in DBEntities.Customer select c).ToList<Customer>();
foreach (Customer customer item in customers)
{
customer.FirstName = ....
... etc, other code here
}
DBEntities.SaveChanges();
答案 2 :(得分:3)
好的,我遇到了同样的问题。现在我没有只有大约20K的百万条记录,但是我想要处理的表存储图像,所以当将表处理到List时需要太长时间,即使在桌面应用程序上也是如此。
我一直在使用LinqToSql,因为它出来了,它在LinqToSql中运行正常,所以当我看到它在Entity中不起作用时,我有点生气。它是愚蠢的微软并没有让它在实体中运作,但这是解决方法。制作2个上下文对象。一个用于列表,另一个用于更新,如下所示。
entityList _imgList = new entityList();
entityList _imgSave = new entityList();
// Now the 1st time I did this I got the whole record like follows.
var _imgList = _imgList.Images.where( i=> i.NotProcessed == false);
foreach(Images _img_p in imgList)
{
if(something)
{
Images _img = _imgSave.Single(i=> i.ID == _img_p.ID);
_img.NotProcessed == true;
imgSave.SaveChanges();
}
}
imgList.dispose();
imgSave.dispose();
// After i verified this worked I figured why do I need to whole record to loop though so I changed it to just get the ID then process my loop as follows, and it works great.
var _imgIds = _imgList.Images.where( i=> i.NotProcessed == false ).select(i=>i.ID);
foreach(long _imgID in imgList)
{
Images _img = _imgSave.Single(i=> i.ID == _imgID);
if(something)
{
_img.NotProcessed == true;
imgSave.SaveChanges();
}
}
imgList.dispose();
imgSave.dispose();
您可以在我的博文(ASP.Net Help Blog)
中查看更多内容答案 3 :(得分:0)
感谢您对循环后的SavingChanges的建议,我没有想到这一点。但是我必须处理超过1百万条记录,这并不是那么多,但是在每个循环中都会执行一些处理。所以我有点担心,需要花费大量时间来循环更新信息的1百万条记录,然后花点时间发布更改。
我也知道EntityFramework可能不是最好的方法,但我对学习Entity Framework的功能和限制感兴趣。
还要注意var列表实际上返回Customer类型的ObjectQuery。因此,即使不转换为列表,也可以使用Customer变量数据类型实际编写foreach循环。
我想知道的问题是为什么我不能在循环期间在同一个上下文对象(DBEntities)中发布更改?