实体框架:为什么人们将.AsEnumerable()与EF查询一起使用 [英] Entity Framework: Why people use .AsEnumerable() along with EF query

查看:48
本文介绍了实体框架:为什么人们将.AsEnumerable()与EF查询一起使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从未在EntityFramework查询中使用 .AsEnumerable().

I have never yet used .AsEnumerable() in an EntityFramework query.

请参见下面的示例,并告诉我为什么他们在 Select 之前使用 .AsEnumerable()吗?

See the below example and tell me why they use .AsEnumerable() before Select ?

他们可以不直接使用 Select 吗?

Could they not just use Select directly?

请在下面的查询中告诉我使用 .AsEnumerable()的原因.

Please tell me the reason for the usage of .AsEnumerable() here in below query.

为什么他们使用 .ToArray()而不是 .Tolist()?

Why did they use .ToArray() instead of .Tolist() ?

private IEnumerable<AutoCompleteData> GetAutoCompleteData(string searchTerm)
{
    using (var context = new AdventureWorksEntities())
    {
        var results = context.Products
            .Include("ProductSubcategory")
            .Where(p => p.Name.Contains(searchTerm)
                        && p.DiscontinuedDate == null)
            .AsEnumerable()
            .Select(p => new AutoCompleteData
                                {
                                    Id = p.ProductID,
                                    Text = BuildAutoCompleteText(p)
                                })
            .ToArray();
        return results;
    }
}

推荐答案

AsEnumerable AsQueryable 之间的区别在于,可枚举包含创建枚举器的所有信息.获取枚举器后,您可以要求第一个元素,如果有,则可以获取下一个.

The difference between AsEnumerable and AsQueryable is that the enumerable contains all information to create an enumerator. Once you've got the enumerator you can ask for the first element, and if there is one, you can get the next one.

Queryable 不保存用于创建枚举器的信息.它包含一个 Expression 和一个 Provider . Provider 知道哪个进程必须执行 Expression 以及该进程使用哪种语言.通常,另一个过程是数据库管理系统,而语言是SQL.

The Queryable does not hold the information to create the enumerator. It holds an Expression and a Provider. The Provider knows which process must execute the Expression and which language this process uses. Quite often the other process is a database management system, and the language is SQL.

Queryable.Select(...)仍然是 IQueryable ,这意味着尚未执行查询.Select函数仅更改了 Expression .

The result of a Queryable.Select(...) is still an IQueryable, meaning that the query is not performed yet. The Select function only changed the Expression.

仅当您请求枚举器时,要么通过调用 GetEnumerator()显式地请求,或者通过调用 foreach 隐式地请求,或者是诸如 ToList() ToDictionary() FirstOrDefault() Sum() Provider code>会将表达式转换为执行过程可以理解并执行查询的格式.将数据传输到本地进程后,将创建枚举数.

Only if you ask for the Enumerator, either explicitly by calling GetEnumerator(), or implicitly by calling foreach, or one of the non-deferred execution functions like ToList(), ToDictionary(), FirstOrDefault(), Sum(), the Provider will translate the expression into the format that the execution process understands and execute the query. Once the data is transported to the local process the enumerator is created.

A,有时候您想在查询中调用自己的函数.SQL不知道这些功能,因此提供程序无法将此类 Expressions 转换为SQL.实际上,DbContext的提供程序甚至不知道所有Linq函数.请参阅支持和不支持的Linq方法

Alas, sometimes you want to call your own functions in your query. SQL does not know these functions, and thus the Provider can't translate such Expressions into SQL. In fact, the provider of DbContext does not even know all Linq functions. See supported and unsupported Linq methods

那是您使用 AsEnumerable()的时刻.如果您要求枚举器(例如,在您的 foreach 中),则提供程序将转换表达式,直到 AsEnumerable ;为止.将其发送到执行过程,并将所有数据传输到本地过程.之后,查询将为 AsEnumerable :其余的LINQ将在本地内存中执行,因此可以调用您的本地函数.

That is the moment when you use AsEnumerable(). If you ask for the Enumerator (in your foreach for example), the Provider will translate the Expression until AsEnumerable; send it to the execution process and transport all data to local process. After that, the query will be AsEnumerable: the rest of the LINQ will be performed in local memory, and thus your local functions can be called.

您当然可以使用ToList()将所有数据提取到本地内存中,然后继续执行linq.但是,如果您只想要第一个元素或其他每个元素,那将是一种浪费.

You could of course use ToList() to fetch all data to local memory and continue your linq after that. But that would be a waste if you'd only want the first element, or every other one.

这使我想起最后一句话:将数据从DBMS传输到本地内存是较慢的部分之一.尝试将这种传输限制为仅实际使用的数据.

This brings me to the final remark: the transport of the data from the DBMS to your local memory is one of the slower parts. Try to limit this transport to only the data you'll actually use.

例如:如果您的老师和学生之间存在一对多关系,请不要获取老师和他的学生,因为您将多次运输 Student.TeacherId ,它们的值都与 Teacher.Id 相同.相反,只选择您真正想要使用的数据

For example: if you have a one-to-many relation between a Teacher and his Students, don't fetch the Teacher and his Students, because you'll transport Student.TeacherId many times, and they will all have the same value as Teacher.Id. Instead, only select the data you really want to use

这篇关于实体框架:为什么人们将.AsEnumerable()与EF查询一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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