.NET EntityFramework: «Произошла ошибка при запуске транзакции в соединении провайдера. Подробности см. Во внутреннем исключении» - PullRequest
8 голосов
/ 18 февраля 2010

Использование Entity Framework в .NET Я хочу просмотреть список элементов, возвращенных из базы данных, и выполнить обновления.

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 С. Харгроувс предлагает перейти на IList, и это решение.

Не пробовал это, я уверен, что это будет работать, но даже это работает, я хочу знать, почему я не могу обновить элемент во время цикла? Это происходит в моей локальной среде разработки, когда другие пользователи не обращаются к базе данных.

Спасибо ...

Ответы [ 4 ]

11 голосов
/ 17 февраля 2011

Когда вы обновляете базу данных, используя 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
3 голосов
/ 19 июня 2011

Хорошо, я столкнулся с той же проблемой. В настоящее время у меня нет миллиона записей только около 20 КБ, но в таблице, которую я хочу обработать, хранятся изображения, поэтому при обработке таблицы в Список занимает слишком много времени, даже в настольном приложении.

Я использую LinqToSql с момента его выхода, и он прекрасно работает в LinqToSql, поэтому я был немного взбешен, когда увидел, что он не работает в Entity. И это глупо, что Microsoft не заставила это работать в 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 )

3 голосов
/ 18 февраля 2010

Я бы согласился составить список. Затем в вашем foreach вместо элемента Object в qry используйте Customer в qry. В этом сценарии вы действительно работаете с объектами заказчика, а не только с объектами. В большинстве случаев вы не захотите вызывать SaveChanges () в foreach, потому что он будет выполнять команду обновления на сервере при каждом запуске. Если вы сделаете это после 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();
0 голосов
/ 18 февраля 2010

Спасибо за рекомендацию по SavingChanges после цикла, я не думал об этом. Однако мне нужно обработать более 1 миллиона записей, это не так уж много, но есть некоторая обработка, которая будет выполняться во время каждого цикла. Поэтому я немного обеспокоен тем, что потребуется много времени, чтобы зациклить 1 миллион записей, обновляющих информацию, а затем потребуется некоторое время, чтобы опубликовать изменения.

Я также знаю, что EntityFramework, вероятно, не лучший подход, но меня интересует изучение возможностей и ограничений Entity Framework.

Также просто отметим, что список var на самом деле возвращает ObjectQuery типа Customer. Таким образом, цикл foreach на самом деле может быть записан, как указано выше, с использованием типа данных переменной Customer даже без преобразования в список.

Опять же, мой вопрос, который мне хотелось бы знать, - почему я не могу опубликовать изменение в одном и том же объекте контекста (DBEntities) во время цикла?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...