Entity Framework (EF) OutOfMemoryException - PullRequest
5 голосов
/ 12 мая 2011

У меня> 67000 записей, поступающих в мою систему из другого источника.После применения бизнес-правил к этим записям я должен сохранить их в базе данных.Для этого я использую следующий код:

        using (var context = new MyEntities())
        {
            var importDataInfo = context.ImportDataInfoes.First(x => x.ID == importId);

            importedRecords.ForEach(importDataInfo.ValuationEventFulls.Add);

            context.SaveChanges();
        }

После выполнения кода я получаю следующую ошибку (OutOfMemoryException)

    Error in executing code|Exception of type 'System.OutOfMemoryException' was thrown.*   at System.Data.Mapping.Update.Internal.KeyManager.<WalkGraph>d__5.MoveNext()
   at System.Data.Mapping.Update.Internal.KeyManager.GetPrincipalValue(PropagatorResult result)
   at System.Data.Mapping.Update.Internal.UpdateCompiler.GenerateValueExpression(EdmProperty property, PropagatorResult value)
   at System.Data.Mapping.Update.Internal.UpdateCompiler.BuildSetClauses(DbExpressionBinding target, PropagatorResult row, PropagatorResult originalRow, TableChangeProcessor processor, Boolean insertMode, Dictionary`2& outputIdentifiers, DbExpression& returning, Boolean& rowMustBeTouched)
   at System.Data.Mapping.Update.Internal.UpdateCompiler.BuildInsertCommand(PropagatorResult newRow, TableChangeProcessor processor)
   at System.Data.Mapping.Update.Internal.TableChangeProcessor.CompileCommands(ChangeNode changeNode, UpdateCompiler compiler)
   at System.Data.Mapping.Update.Internal.UpdateTranslator.<ProduceDynamicCommands>d__0.MoveNext()
   at System.Linq.Enumerable.<ConcatIterator>d__71`1.MoveNext()
   at System.Data.Mapping.Update.Internal.UpdateCommandOrderer..ctor(IEnumerable`1 commands, UpdateTranslator translator)
   at System.Data.Mapping.Update.Internal.UpdateTranslator.ProduceCommands()
   at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)
   at System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache)
   at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)

Я использую EF 4.0.

Myвопрос есть ли ограничение на количество записей для сохранения?Как лучше всего сохранять большое количество записей (сохранять их порциями? Как насчет транзакций?).

Заранее всем спасибо.

Ответы [ 2 ]

4 голосов
/ 12 мая 2011

Как правило, .NET ограничивается адресацией 2 ГБ памяти в одной коллекции или другом объекте.Это связано с тем, что даже в 64-разрядной среде индексаторы используют 32-разрядные целые числа (с максимальным значением 2 миллиарда и изменением).Даже для простых типов данных, таких как целые числа, размер одного целого означает, что в одном массиве может храниться только 500 миллионов целых.Для более крупных типов значений, таких как структуры, максимальное количество элементов коллекции становится действительно небольшим.

Если вы работаете в 32-битной среде, такой как Windows XP, существуют даже более низкие пределы;максимальный объем памяти для ВСЕЙ ПРОГРАММЫ не может превышать 2 ГБ.Это накладывает некоторые довольно высокие ограничения на ETL, подобный вашему, и я совсем не удивлюсь тому, что вашей программе не хватает памяти, пытающейся обработать 67k записей в памяти за один раз.

Решение состоит в том, чтобы обрабатыватьзаписи небольшими партиями, если можете.Попробуйте построить оператор на основе идентификатора, в котором вы возвращаете первые 100 записей, где идентификатор (возможно, автоматически сгенерированный) превышает самый большой идентификатор, который вы уже получили.Как только запись обработана, утилизируйте ее (или просто осиротьте и дайте GC выполнить свою работу).

4 голосов
/ 12 мая 2011

Возможно, вы захотите отправлять эти данные партиями, возможно, из 1024 записей за один раз.

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

Распределенные транзакции могут применяться только к серверу, на котором запущена служба координатора распределенных транзакций Microsoft (MS-DTC).При работе с распределенными транзакциями заметно снижается производительность.

...