首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在LINQ中使用表达式时SQL查询生成效率低下

在LINQ中使用表达式时SQL查询生成效率低下
EN

Stack Overflow用户
提问于 2020-05-06 02:23:36
回答 3查看 38关注 0票数 0

考虑以下代码,其中dbContext是SQL Server数据库上下文,ExamplesDbSet

代码语言:javascript
运行
复制
this.dbContext.Examples.Take(5).ToList();
Enumerable.Take(this.dbContext.Examples, 5).ToList();

第一行按照预期工作,并以以下方式转换为SQL:

代码语言:javascript
运行
复制
SELECT TOP(5) * FROM Examples

但是,第二行首先获取所有行,然后应用Take运算符。为什么会这样呢?

因为我使用表达式来构建动态lambda,所以我必须使用第二种方法(Enumerable.Take):

代码语言:javascript
运行
复制
var call = Expression.Call(
    typeof(Enumerable),
    "Take",
    new[]{ typeof(Examples) },
    contextParam,
    Expression.Constant(5)
);

不幸的是,第一种方法在使用表达式时不起作用,程序的当前体系结构迫使我动态构建一个lambda。

为什么第二种方法获取所有行,我如何防止它以便在表达式中有效地使用它?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-05-06 03:15:27

您调用的不是同一个方法。第一行是调用Queryable.Take,而不是Enumerable.Take

由于DbSet实现了IQueryable<>IEnumerable<>,而IQueryable<>实现了IEnumerable<>,因此编译器将IQueryable<>视为更具体的类型。因此,当它解析要调用的Take扩展方法时,它会确定Queryable.Take(...)是正确的方法,因为它需要一个IQueryable<>作为第一个参数。

这一点很重要,因为IQueryable<>接口允许将LINQ查询构建为表达式树,并将其计算为SQL语句。当您切换到将IQueryable<>视为IEnumerable<>的那一刻,您就失去了这种行为,并且切换到只能迭代在此之前构建的任何查询的结果。

试试这个:

代码语言:javascript
运行
复制
Queryable.Take(this.dbContext.Examples, 5).ToList();

或者这样:

代码语言:javascript
运行
复制
var call = Expression.Call(
    typeof(Queryable),
    "Take",
    new[]{ typeof(Examples) },
    contextParam,
    Expression.Constant(5)
);
票数 3
EN

Stack Overflow用户

发布于 2020-05-06 03:02:06

它之所以有效,是因为在第一条语句中

dbContext.Examples.Take(5).ToList(); -您正在IQuerable接口上调用.Take(5),LINQ to SQL提供程序可以在该接口上对数据库执行适当的SQL语句。

如果需要在数据库端执行查询,则必须在IQuerable接口实例上构造查询。

Enumerable.Take是IEnumarble引用,在从db中获取所有数据后,将在内存中执行Take方法

票数 1
EN

Stack Overflow用户

发布于 2020-05-06 02:46:58

"this.dbContext.Examples“获取所有数据,然后进行Enumerable.Take过滤,并从中提取前5个数据。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61620258

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档