如何从 LINQ to Entities 查询流式传输数据?

Tre*_*ink 6 c# entity-framework-6

我想知道如何使用 EF6 从 SQL Server 流式传输数据。

假设有这些课程

  • 人员信息库
  • EFPerson(EF模型)
  • DomainPerson(领域模型)
  • PersonUsingClass

假设 PersonUsingClass 依赖于获取一堆 DomainPerson。假设业务规则规定不允许 EFPerson 离开 PersonRepository。

通常我会有一个如下所示的存储库方法:

    public IEnumerable<DomainPerson> GetPeople()
    {
        using (var db = new efContext())
        {
            IQueryable efPeople = db.Person.Where(someCriteria);

            foreach (var person in efPeople)
            {
                yield return person.ToDomainPerson();
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

使用我这里的代码,所有内容都会在执行 foreach 时加载到内存中。我可以通过将 IQueryable 返回到 PersonUsingClass 来实现流式处理,但这会将 EF 模型暴露给该类,这是一种不需要的情况。

难道真的不可能在流数据的同时隐藏 EF 模型吗?还是有什么我不知道的事情?

Oli*_*ver 5

您创建的方法会迭代IQueryable<>EF 创建的对象。

该变量具有延迟执行,因此在内部,EF 仅在迭代时(即首次调用时)IQueryable<>才会调用数据库。IQueryable<>.MoveNext()

此外,如果您曾经使用过手动进行数据库调用SqlDataReader,您会发现可以.Read()逐一查询查询结果,而无需将所有记录加载到内存中。EF 很可能以这种方式传输记录(这是我的假设,它可能取决于您的特定 EF 设置)。

您的方法返回一个IEnumerable<>对象,该对象也受到延迟执行的影响。通过调用创建此实例GetPeople()不会导致数据库调用。

当您的方法的结果被迭代时,您将触发内部对象的迭代IQueryable<>并一一转换结果。

所以:

该方法中没有记录加载到内存中(除非 EF 在内部进行一些缓存)。如果您迭代该方法的结果,那么您将逐条迭代每条记录。

如果您对该方法的结果调用.ToList()or ,那么记录将被加载到内存中。.ToArray()