实体框架(EF)OutOfMemoryException

时间:2011-05-12 15:50:26

标签: c# .net entity-framework entity-framework-4 out-of-memory

我有>来自其他来源的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。

我的问题是要保存的记录数量有限制吗?保存大量记录的最佳做法是什么(将它们保存在块中?交易怎么样?)。

提前感谢大家。

2 个答案:

答案 0 :(得分:4)

您可能希望一次将这些数据分批发送到大约1024条记录中。

您可以包装在事务中批处理记录的循环,以便您可以根据需要回滚整个序列。请注意,此事务很可能会升级为分布式事务。

分布式事务只能应用于运行Microsoft分布式事务处理协调器(MS-DTC)服务的服务器。在处理分布式事务时会有明显的性能损失。

答案 1 :(得分:4)

通常,.NET仅限于在单个集合或其他对象中处理2GB内存。这是因为即使在64位环境中,索引器也使用32位整数(最大值为20亿并且更改)。即使对于像整数这样的简单数据类型,单个int的大小意味着只能在单个数组中存储5亿个int。对于像结构这样的较大值类型,集合的最大元素数量非常小。

如果您处于像Windows XP这样的32位环境中,则存在更低的限制;整个程序的最大内存空间不能超过2GB。这对像你这样的ETL有一些相当高的限制,我不会对你的程序内存耗尽试图同时处理67k内存中的记录感到惊讶。

如果可以,解决方案是以较小批量处理记录。尝试根据ID构建一个语句,返回前100条记录,其中ID(希望自动生成)大于您已检索的最大ID。处理完记录后,处理它(或者只是孤立它并让GC完成它的工作)。