C# 实体框架如何遍历过大的集合?

C# 实体框架如何遍历过大的集合?,c#,.net,entity-framework,sqldatareader,C#,.net,Entity Framework,Sqldatareader,我不熟悉实体框架 我有一个担忧: 我需要遍历通过LINQ收集的大量数据,以匿名类型组合来自不同实体的两个属性 如果我需要一个接一个地读取此查询的返回项直到结束,那么由于集合很大或EF隐式使用SqlDataReader,我是否有OutOfMemory异常的风险 (或者我应该使用EntityDateReader来确保我是按顺序读取数据库的(但随后我必须以字符串的形式生成查询))在我看来,有两件事可以做,首先使用关闭跟踪。因为不跟踪在大多数情况下会将内存集减半,这可能就足够了 如果您的集合仍然太大,请

我不熟悉实体框架

我有一个担忧:

我需要遍历通过LINQ收集的大量数据,以匿名类型组合来自不同实体的两个属性

如果我需要一个接一个地读取此查询的返回项直到结束,那么由于集合很大或EF隐式使用SqlDataReader,我是否有OutOfMemory异常的风险


(或者我应该使用EntityDateReader来确保我是按顺序读取数据库的(但随后我必须以字符串的形式生成查询))

在我看来,有两件事可以做,首先使用关闭跟踪。因为不跟踪在大多数情况下会将内存集减半,这可能就足够了

如果您的集合仍然太大,请使用skip and take将结果集合分块拉下来。您还应该将其与AsNoTracking结合使用,以确保跟踪不会占用内存

编辑:

例如,您可以使用如下内容循环1000个块中的所有项目。下面的代码一次只能在内存中保存1000项

int numberOfItems = ctx.MySet.Count();

for(int i = 0; i < numberOfItems + 1000; i+=1000)
{
    foreach(var item in ctx.MySet.AsNoTracking().Skip(i).Take(1000).AsEnumerable())
    {
         //do stuff with your entity
    }
}
int numberOfItems=ctx.MySet.Count();
对于(int i=0;i
如果数据量如您所说的那么大,我建议您在这种情况下不要使用EF。EF很好,但有时需要回退并使用标准SQL来获得更好的性能

请看Dapper.NET

如果您真的想在任何情况下都使用EF,我建议您使用有界上下文(多个DBContexts)

在多个较小的上下文中拆分模型将提高性能,因为当EF创建上下文的内存模型时,您将使用更少的资源

上下文越大,用于生成的资源就越多 并保持内存模式


此外,在共享多个上下文实例时,您还可以分离附加,这样您仍然不会加载所有模型。

这实际上不是一个性能问题,但即使是,使用dapper等平台所带来的性能提升也没有您所建议的那么大。使用大型数据集时,dapper的批量选择性能比EF提高了约25%,但我认为这在计算方面相当微不足道。看看我在这方面的性能统计:在实际内存使用方面,dapper和EF在没有跟踪的情况下几乎没有什么区别。我不太确定你关于有界上下文的意思,因为这是一个DDD术语,它与性能或内存消耗无关,更关心逻辑分离。此外,通过将detach与EF一起使用来减少内存不是一个好主意,因为在调用detach时,您已经消耗了内存。AsNoTracking在这里是一个更好的解决方案,因为它意味着永远不会将内存分配给跟踪器减少内存,因为EF在创建上下文的内存模型时会消耗更少的内存。如果他必须处理相同数量的对象,则无论他如何划分,都将占用相同数量的内存。对不起;你所说的“使用skip and take将结果集分块下拉”实际上是什么意思?