2012-06-13 5 views
1

Существующий фрагментEf4 SaveChanges как избежать из исключения памяти

foreach (var ownerCandidates in ownerToCandidatesDictionary) 
    { 
    foreach (var candidate in ownerCandidates.Value) 
    { 
     transactionEntities.AddToSomeEntity(someObject) 
    } 
    } 
       transactionEntities.SaveChanges(System.Data.Objects.SaveOptions.AcceptAllChangesAfterSave); 

переписывает в

int i = 0 ; 
    foreach (var ownerCandidates in ownerToCandidatesDictionary) 
    { 
     foreach (var candidate in ownerCandidates.Value) 
     { 
      transactionEntities.AddToSomeEntity(someObject) 
      } 
      if (i++ % 1000 == 0) 
      { 
       transactionEntities.SaveChanges(System.Data.Objects.SaveOptions.AcceptAllChangesAfterSave); 
      } 
    } 

transactionEntities.SaveChanges(System.Data.Objects.SaveOptions.AcceptAllChangesAfterSave); 

дает нам такую ​​же функциональность в случае успешного завершения программы? Моя забота, которую мы продолжаем добавлять, делает SaveChanges в цикле работать только с тем, что было добавлено после предыдущих SaveChanges. У нас есть сбережения здесь? Если это не так, как оригинальный фрагмент может быть изменен, чтобы избежать

12/06/2012 7:50:37 PM : System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown. 
    at System.Data.Mapping.Update.Internal.Propagator.Project(DbProjectExpression node, PropagatorResult row, TypeUsage resultType) 
    at System.Data.Mapping.Update.Internal.Propagator.Visit(DbProjectExpression node) 
    at System.Data.Common.CommandTrees.DbProjectExpression.Accept[TResultType](DbExpressionVisitor`1 visitor) 
    at System.Data.Mapping.Update.Internal.Propagator.Propagate(UpdateTranslator parent, EntitySet table, DbQueryCommandTree umView) 
    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) 

ответ

6

Последующий вызов SaveChanges() не будет иметь никакого эффекта, если изменения не будут внесены в сущности, установленной после предыдущих SaveChanges(). После сохранения SaveChanges() в базе данных будет новая партия. Пакетирование - это вариант преодоления исключения OutOfMemoryException во время огромных вставок с EntityFramework. Фактически SaveChanges() должен быть вызван только один раз, но в вашем случае, поскольку данные огромны, его необходимо разделить на партии.

Также при добавлении сущности навалом, чтобы добиться значительных улучшений производительности, временно отключите автоматическое обнаружение изменений, установив AutoDetectChangesEnabled на значение false. Here is the info

+0

Но как насчет фрагментов кода, которые я включил, фрагмент 2 - вы видите партии там. – MicMit

+1

Да, строка 'if (i ++% 1000 == 0)' делает партии. С каждой порцией 1000 вставок. –

Смежные вопросы