IQueryable的排序依据与Func键<的TModel,TValue> : 发生了什么 [英] IQueryable OrderBy with Func<TModel, TValue> : what's happening

查看:603
本文介绍了IQueryable的排序依据与Func键<的TModel,TValue> : 发生了什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从这个问题
传递一个选择器功能时,排序依据是不转换成SQL

  Func键<表1 ,串> F = X => x.Name; 
变种T = db.Table1.OrderBy(F).ToList();



转换为SQL语句是:



  SELECT 
[Extent1]。[ID] AS [ID],
[Extent1]。[名] AS [名]
从[DBO]。[表1] AS [Extent1]

确定。



我可以理解的代码编译:的IQueryable 的IEnumerable ,它有一个排序依据的方法服用<$继承C $ C> Func键<的TModel,TValue> 为参数



我可以理解的ORDER BY子句不能在SQL生成的,如。我们没有通过的表达式来; Func键<的TModel,TValue>> 作为排序依据参数(一个IQueryable的)



但是,什么幕后发生了什么?发生了错误的排序依据的方法是什么?没有 ?我看不出如何以及为什么...任何光线在我的夜晚?


解决方案

由于˚F 为代表,而不是一个表达式,编译器采的IEnumerable 排序依据扩展方法,而不是的的IQueryable 之一。



这则意味着所有的结果是从数据库中获取的,因为排序是然后在内存中完成,就像它是LINQ到对象。也就是说,在内存中,排序只能通过获取所有记录完成的。



当然,在现实中这仍然没有实际发生,直到你开始枚举结果 - 而你的情况,你做的直线距离,因为你渴望加载与您的来电了ToList()


$ b $的结果。 b

更新响应您的评论



看来你的问题是一样关于的IQueryable / 的IEnumerable 二元但从引入模糊的点是危险的。这真的不是:

  t.OrderBy(R = GT; r.Field)

C#看到拉姆达为表达式来;> code> T 的IQueryable 然后选择的IQueryable 扩展方法。这是一样的字符串传递给一个重载的方法用一个字符串的变量对象超载 - 在字符串版本将被使用,因为它的的最好体现



正如叶普指出,这实际上是因为眼前的接口时,继承了之前的接口


$ b $ :b

  t.AsEnumerable()排序依据(R = GT; r.Field)

C#不能看到的IQueryable 了,所以对待拉姆达为 Func键< A,b> ,因为这是它的下一个最好的代表。 (只有一个对象的等效方法是在我的字符串可用 / 对象类比之前



和然后最后你的例子:

  Func键< T,串> F = R => r.Field; 
t.OrderBy(F);

有是的没有可能的方式的,开发者编写这些代码可以预计这将被视为一个较低的水平分量的表达式转换为SQL,除非开发商根本不理解的委托和表达之间的差异的。如果是这样的话,那么读了一点点解决问题。





我现在认识到,通过添加此编辑我现在@IanNewson无效的注释下 - 但我希望它提供了一个令人信服的理由是有道理的:)


With the code given from this question 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();

The translated SQL is:

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

OK.

I can understand that the code compiles : IQueryable inherits from IEnumerable, which have an OrderBy method taking a Func<TModel, TValue> as parameter.

I can understand that the ORDER BY clause is not generated in SQL, as we didn't pass an Expression<Func<TModel, TValue>> as the OrderBy parameter (the one for IQueryable)

But what happens behind the scene ? What happens to the "wrong" OrderBy method ? Nothing ? I can't see how and why... Any light in my night ?

解决方案

Because f is a delegate rather than an expression, the compiler picks the IEnumerable OrderBy extension method instead of the IQueryable one.

This then means that all the results are fetched from the database, because the ordering is then done in memory as if it were Linq to Objects. That is, in-memory, the ordering can only be done by fetching all the records.

Of course, in reality this still doesn't actually happen until you start enumerating the result - which in your case you do straight away because you eager-load the result with your call to ToList().

Update in response to your comment

It seems that your question is as much about the IQueryable/IEnumerable duality being 'dangerous' from the point of view of introducing ambiguity. It really isn't:

t.OrderBy(r => r.Field)

C# sees the lambda as an Expression<> first and foremost so if t is an IQueryable then the IQueryable extension method is selected. It's the same as a variable of string being passed to an overloaded method with a string and object overload - the string version will be used because it's the best representation.

As Jeppe has pointed out, it's actually because the immediate interface is used, before inherited interfaces

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

C# can't see an IQueryable any more, so treats the lambda as a Func<A, B>, because that's it's next-best representation. (The equivalent of only an object method being available in my string/object analogy before.

And then finally your example:

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

There is no possible way that a developer writing this code can expect this to be treated as an expression for a lower-level component to translate to SQL, unless the developer fundamentally doesn't understand the difference between a delegate and an expression. If that's the case, then a little bit of reading up solves the problem.

I don't think it's unreasonable to require a developer to do a little bit of reading before they embark on using a new technology; especially when, in MSDN's defence, this particular subject is covered so well.

I realise now that by adding this edit I've now nullified the comment by @IanNewson below - but I hope it provides a compelling argument that makes sense :)

这篇关于IQueryable的排序依据与Func键&LT;的TModel,TValue&GT; : 发生了什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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