如何将数据从LINQ传输到实体查询? [英] How can data be streamed from a LINQ to Entities query?

查看:66
本文介绍了如何将数据从LINQ传输到实体查询?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道如何使用EF6从SQL Server流数据.

I'm wondering how one would go about streaming data from SQL server using EF6.

假设有这些课程

  • PersonRepository
  • EFPerson(EF模式)
  • DomainPerson(域模型)
  • PersonUsingClass

假设PersonUsingClass依赖于获得一堆DomainPersons. 假设业务规则规定不允许EFPersons离开PersonRepository.

Assume that PersonUsingClass depends on getting a bunch of DomainPersons. Assume that business rules dictate that EFPersons aren't allowed to leave the PersonRepository.

通常我会有一个类似这样的存储库方法:

Normally I'd have a repository method looking like this:

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

            foreach (var person in efPeople)
            {
                yield return person.ToDomainPerson();
            }
        }
    }

使用我在这里的代码,执行foreach时,所有内容都会加载到内存中.我可以通过将IQueryable返回给PersonUsingClass来实现流传输,但这会使EF模型暴露给该类,这是不希望的情况.

With the code I have here, everything would be loaded into memory upon doing the foreach. I could achieve the streaming by returning the IQueryable to the PersonUsingClass, but that exposes the EF models to that class, which is an unwanted scenario.

真的真的不可能隐藏EF模型,为什么同时传输数据吗?还是有我不知道的东西?

Is it really impossible to hide away the EF models why streaming data at the same time? Or is there something I don't know?

推荐答案

您创建的方法在由EF创建的IQueryable<>对象上进行迭代.

The method you have created iterates over an IQueryable<> object that's created by EF.

IQueryable<>变量已推迟执行,因此在内部,EF仅在迭代IQueryable<>时(即首次调用.MoveNext()时)才对数据库进行调用.

The IQueryable<> variable has deferred execution, therefore internally, EF will only make the call to the database when the IQueryable<> is iterated over (i.e. when .MoveNext() is first called).

此外,如果您曾经使用SqlDataReader手动滚动数据库调用,则会发现可以.Read()一次查询的结果,您无需加载全部记录到内存中. EF可能以这种方式对记录进行流式传输(这是我的假设,这可能取决于您的特定EF设置).

Additionally, if you have ever hand-rolled a database call using SqlDataReader, you'll see that it is possible to .Read() results of a query one-by-one, you don't need to load all records into memory. It's likely that the records are being streamed in this way by EF (this is an assumption on my part, it may depend on your specific EF setup).

您的方法将返回一个IEnumerable<>对象,该对象也将被推迟执行.通过调用GetPeople()创建此实例不会导致数据库调用.

Your method is returning an IEnumerable<> object which is also subject to deferred exeution. Creating an instance of this by calling GetPeople() will not lead to a database call.

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

When the result of your method is iterated over, you're then triggering the iteration over the internal IQueryable<> object and transforming the results one by one.

因此:

该方法不会将任何记录加载到内存中(除非EF在内部进行了一些缓存).如果您迭代该方法的结果,那么您将逐个迭代每个记录.

No records are being loaded into memory in that method (unless EF is doing some caching internally). If you iterate over the result of that method then you are iterating over each record one by one.

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

If you call .ToList() or .ToArray() on the result of that method then records will be loaded into memory.

这篇关于如何将数据从LINQ传输到实体查询?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆