gpt4 book ai didi

c# - IQueryable OrderBy 与 Func : what's happening

转载 作者:太空狗 更新时间:2023-10-29 20:05:30 25 4
gpt4 key购买 nike

使用这个问题给出的代码 OrderBy is not translated into SQL when passing a selector function

Func<Table1, string> f = x => x.Name;
var t = db.Table1.OrderBy(f).ToList();

翻译后的 SQL 是:

SELECT 
[Extent1].[ID] AS [ID],
[Extent1].[Name] AS [Name]
FROM [dbo].[Table1] AS [Extent1]

好的。

我可以理解代码编译:IQueryable继承自 IEnumerable ,它有一个 OrderBy 方法采用 Func<TModel, TValue>作为参数。

我可以理解 ORDER BY 子句不会在 SQL 中生成,因为我们没有传递 Expression<Func<TModel, TValue>>作为 OrderBy 参数(用于 IQueryable 的参数)

但是幕后发生了什么? “错误的”OrderBy 方法会怎样?没有 ?我看不出如何以及为什么......我的夜晚有灯吗?

最佳答案

因为 f是委托(delegate)而不是表达式,编译器选择 IEnumerable OrderBy扩展方法而不是 IQueryable一个。

这意味着所有的结果都是从数据库中获取的,因为排序是在内存中完成的,就好像它是 Linq to Objects 一样。也就是说,在内存中,排序只能通过获取所有记录来完成。

当然,实际上,直到您开始枚举结果,这仍然不会真正发生 - 在您的情况下,您会立即这样做,因为您通过调用 ToList() 来急切加载结果。 .

更新以回应您的评论

您的问题似乎与 IQueryable 有关/IEnumerable从引入歧义的角度来看,二元性是“危险的”。它真的不是:

t.OrderBy(r => r.Field)

C# 将 lambda 视为 Expression<>首先也是最重要的,如果t是一个 IQueryable然后是 IQueryable选择扩展方法。与string的变量相同使用 string 传递给重载方法和 object过载 - string将使用版本,因为它是最佳表示

正如 Jeppe 所指出的,这实际上是因为在继承接口(interface)之前使用了直接接口(interface)

t.AsEnumerable().OrderBy(r => r.Field)

C# 看不到 IQueryable不再是,所以将 lambda 视为 Func<A, B> ,因为这是次佳表示。 (相当于在我之前的 object/string 类比中只有一个 object 方法可用。

最后是你的例子:

Func<t, string> f = r => r.Field;
t.OrderBy(f);

不可能编写此代码的开发人员可以期望将其视为低级组件的表达式以转换为 SQL,除非开发人员从根本上不这样做不理解委托(delegate)和表达式之间的区别。如果是这种情况,那么稍微阅读一下就可以解决问题。

我认为要求开发人员在着手使用新技术之前进行一些阅读并不是没有道理的;特别是在 MSDN 的辩护中,这个特定的主题被很好地涵盖了。

我现在意识到,通过添加此编辑,我现在已经取消了下面@IanNewson 的评论 - 但我希望它提供了一个有说服力的有意义的论点:)

关于c# - IQueryable OrderBy 与 Func<TModel, TValue> : what's happening,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12222006/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com