.NET EntityFramework:“在提供程序连接上启动事务时发生错误。有关详细信息,请参阅内部异常”

时间:2010-02-18 00:12:09

标签: .net entity-framework

在.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,这就是解决方案。

没试过,我相信它会起作用,但即使它有效,我想知道为什么我不能在循环期间更新项目?这是在我的本地开发环境中发生的,没有其他用户访问数据库。

谢谢...

4 个答案:

答案 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)中发布更改?