System.OutOfMemoryException db.SaveChanges的实体框架6

时间:2017-04-27 09:46:32

标签: c# entity-framework entity-framework-6

我正在运行使用实体框架将事件插入数据库的批处理作业。总规模各不相同,但大约有350万个事件正常。此列表分为60-500k个事件组,然后添加到数据库中。

然而,当我添加了大约一百万个事件时,我得到System.OutOfMemoryException并且必须重新开始。因此,要完成该程序,它必须现在运行3-4次。如何在调用SaveChanges()之后清除我的数据库对象,这样就不会发生?

public DbSet<Events> Events { get; set; }
...
var groupedList = list.GroupBy(x => x.Import.FileName);
var db = new ApplicationDbContext();

foreach (var group in groupedList)
{
   db.Events.AddRange(group);
   db.SaveChanges();
}

堆栈追踪:

System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
at System.Data.Entity.Core.Mapping.Update.Internal.KeyManager.GetPrincipals(Int32 identifier)
at System.Data.Entity.Core.Mapping.Update.Internal.DynamicUpdateCommand..ctor(TableChangeProcessor processor, UpdateTranslator translator, ModificationOperator modificationOperator, PropagatorResult originalValues, PropagatorResult currentValues, DbModificationCommandTree tree, Dictionary`2 outputIdentifiers)
at System.Data.Entity.Core.Mapping.Update.Internal.UpdateCompiler.BuildInsertCommand(PropagatorResult newRow, TableChangeProcessor processor)
at System.Data.Entity.Core.Mapping.Update.Internal.TableChangeProcessor.CompileCommands(ChangeNode changeNode, UpdateCompiler compiler)
at System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.<ProduceDynamicCommands>d__a.MoveNext()
at System.Linq.Enumerable.<ConcatIterator>d__58`1.MoveNext()
at System.Data.Entity.Core.Mapping.Update.Internal.UpdateCommandOrderer..ctor(IEnumerable`1 commands, UpdateTranslator translator)
at System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.ProduceCommands()
at System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.Update()
at System.Data.Entity.Core.EntityClient.Internal.EntityAdapter.<Update>b__2(UpdateTranslator ut)
at System.Data.Entity.Core.EntityClient.Internal.EntityAdapter.Update[T](T noChangesResult, Func`2 updateFunction)
at System.Data.Entity.Core.EntityClient.Internal.EntityAdapter.Update()
at System.Data.Entity.Core.Objects.ObjectContext.<SaveChangesToStore>b__35()
at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
at System.Data.Entity.Core.Objects.ObjectContext.SaveChangesToStore(SaveOptions options, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction)
at System.Data.Entity.Core.Objects.ObjectContext.<>c__DisplayClass2a.<SaveChangesInternal>b__27()
at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation)
at System.Data.Entity.Core.Objects.ObjectContext.SaveChangesInternal(SaveOptions options, Boolean executeInExistingTransaction)
at System.Data.Entity.Core.Objects.ObjectContext.SaveChanges(SaveOptions options)
at System.Data.Entity.Internal.InternalContext.SaveChanges()
at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
at System.Data.Entity.DbContext.SaveChanges()
at Project.Program.Main(String[] args) in C:\Users\oscar\Documents\Solution\Project\Program.cs:line 135

1 个答案:

答案 0 :(得分:4)

插入一个批处理后,您应该重新创建DbContext以清除ChangeTracker。这不仅可以解决您的内存问题,还可以使事情变得更快。像

这样的东西
foreach (var group in groupedList)
{
   using(var db = new MyDbContext()){
     db.Events.AddRange(group);
     db.SaveChanges();
   }
}