使用Entity Framework和LINQ查询大型数据集时如何避免内存溢出

Sau*_*aul 14 c# linq entity-framework

我有一个处理所有数据库方法的类,包括与实体框架相关的东西.当需要数据时,其他类可以调用此类中的方法,例如

public List<LocalDataObject> GetData(int start, int end);
Run Code Online (Sandbox Code Playgroud)

数据库使用LINQ to EF进行查询,然后调用类可以迭代数据.但由于其他类无法访问EF中的实体,因此我需要对查询执行"ToList()"操作,并将完整数据集提取到内存中.

如果这个集非常大(GB的10s-100s)会发生什么?

有没有更有效的迭代方法,仍然保持松耦合?

Lad*_*nka 21

在Entity框架中使用大型数据集的正确方法是:

  • 使用EFv4和POCO对象 - 它将允许与上层共享对象,而不会引入对Entity框架的依赖
  • 关闭代理创建/延迟加载以将POCO实体与对象上下文完全分离
  • 公开IQueryable<EntityType>允许上层更精确地指定查询并限制从数据库加载的记录数
  • 在数据访问方法中公开IQueryableset MergeOption.NoTrackingObjectQuery.将此设置与关闭代理创建相结合应导致不缓存实体,并且通过查询结果的迭代应始终仅加载单个实体化实体(不缓存已加载实体).

在您的简单场景中,您始终可以检查客户端是否不会询问太多记录,只需触发异常或仅返回最大允许记录.


Kon*_*Kon 5

尽管我喜欢EF用于快速/简单的数据访问,但我可能不会将它用于这种情况.在处理那个大小的数据时,我会选择能够准确返回你需要的存储过程,而不是额外的.然后使用轻量级DataReader填充对象.

DataReader提供无缓冲的数据流,允许程序逻辑按顺序有效地处理来自数据源的结果.在检索大量数据时,DataReader是一个不错的选择, 因为数据不会缓存在内存中.

此外,就内存管理而言,当然要确保将处理非托管资源的代码包装在使用块中以进行正确的处理/垃圾回收.

您也可以考虑实现分页.