什么是LINQ查询表达式和扩展方法之间的区别 [英] What is the difference between LINQ query expressions and extension methods

查看:240
本文介绍了什么是LINQ查询表达式和扩展方法之间的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是两个查询返回相同的数据。其他然后风格,我不知道哪一个更好。



哪些因素会影响这些查询?
什么是使用一种风格比其他的好处呢?



示例1

  VAR X =从s在db.Surveys 
加入在s.ID db.Survey_Questions平方等于sq.Survey_ID
在db.Questions加入●在sq.Question_ID等于q .ID
在q.ID db.Question_Groups加入QG等于qg.Question_ID
,其中s.Type_ID.Equals(TYPEID)及s.Type.Equals(类型)
选择新{问题= sq.Question,状态= sq.Status,GRP = QG};



样本2



  VAR X = db.Surveys.Where(S = GT; s.Type_ID.Equals(TYPEID)及s.Type.Equals(类型))
。加入(db.Survey_Questions,
S => s.ID,
平方=> sq.Survey_ID,
(S,SQ)=>新建
{
=问题sq.Question,
状态= sq.Status
})
。加入(db.Question_Groups,
Q => q.question.ID,
QG => qg.Question_ID,
(q,QG)= GT;新的
{
=问题q.question,
状态= q.status,
组= QG
} ).ToList();


解决方案

更​​新:你有固定的标题,所以忽略了咆哮。



你的问题的标题无关,与你的代码示例。你的问题意味着,一个语法IEnumerable和另一种是IQueryable的,但这是不正确。在您的样品,如果 db.Surveys 是一个IQueryable,那么的 的你的样品使用的IQueryable两者。我会尽量回答的两个的问题。



良好您的两个代码示例是编写相同的LINQ查询(假设只是不同的方式他们是书面)。在样品1中的代码只是简写在样品2中的代码的编译器将码两个样品以相同的方式。想想C#编译器将把方法 INT 可空< System.Int32> 。无论是C#和VB.Net语言提供这个速记查询语法。其他语言可能没有这种语法,你将不得不使用示例2语法。事实上,其他语言可能甚至不支持扩展方法或lambda表达式,你将不得不使用丑陋的语法呢。






更新:



要进一步采取Sander的例子​​,当你写这个(查询理解语法):

$ b $在db.Surveys选择s.Name

$ b b

  VAR surveyNames =从s 
$ b

认为的编译器开启的简写成这样(扩展方法和lambda表达式):

 的IQueryable<串GT; surveryNames = db.Surveys.Select(S => s.Name); 



但实际上,扩展方法和lambda表达式速记自己。编译器会发出这样的事情(不完全是,但只是为了给一个想法):

 表达式来; Func键<调查,串> >选择=委托(调查S){返回s.Name; }; 
&IQueryable的LT;字符串> surveryNames = Queryable.Select(db.Surveys,选择);



注意选择()只是一个在可查询类的静态方法。如果你的.NET语言不支持查询语法,lambda表达式,或扩展的方法,那就是有点你怎么也得自己编写的代码。







什么是用一种风格比其他?



$的好处b $ b

有关小查询,扩展方法可以更为简练:

  VAR项目= source.Where(S = > S取代; 5); 



此外,扩展方法的语法可以更加灵活,比如有条件的WHERE子句:



  VAR项目= source.Where(S = GT; S> 5); 

如果(smallerThanThen)
项= items.Where(S =>氏小于10);
如果(偶数)
项= items.Where(S =&将(S%2)== 0);

返回items.OrderBy(S = GT S);



此外,一些方法只能通过扩展方法的语法(COUNT(),骨料()取(),跳过(),了ToList(),ToArray的()等),所以如果我将使用其中的一个,我通常会写整个查询在此语法来避免混淆两种语法。

  VAR floridaCount = source.Count(S = GT; s.State ==FL); 

VAR项目源=
。凡(S = GT; S> 5)
.Skip(5)
。取(3)
.ToList();

在另一方面,当查询变得更大和更为复杂,查询理解语法可以更清晰,尤其是当你开始用几个加入



在结束时,我通常会使用任何适用于每一个特定的查询更好。






更新:你固定您的标题,所以忽略休息...



现在,关于你的标题:关于LINQ,IEnumerable和IQueryable的非常相似。他们都有几乎相同的扩展方法(选择,其中,计数等),主要(唯一?)的区别是IEnumerable的需要 Func键<锡,兜售> 作为指标与IQueryable的需要表达式来; Func键<锡,兜售>> 作为参数。你同时表达了同样的方式(通常兰巴表达式),但是在内部他们是完全不同的。



IEnumerable的是门口LINQ到对象。在LINQ到对象扩展方法可以算得上任何的IEnumerable(数组,列表,任何你可以用的foreach 迭代)和 Func键<锡,兜售> ; 转换为IL在编译时和运行就像在运行时正常的方法的代码。需要注意的是一些其他的LINQ提供程序使用的IEnumerable,因此实际使用LINQ到幕后对象(LINQ到XML,LINQ到数据集)。



IQueryable的是使用LINQ到SQL,LINQ到需要检查你的查询,而是翻译它直接执行代码的实体,和其他LINQ提供程序。 IQueryable的查询及其表达式来; Func键<锡,兜售>> ,则不会在编译的时候编译成IL。代替的表达式树的创建,并可以在运行时进行检查。这允许语句翻译成其他查询语言(例如T-SQL)。一个表达式树可以被编译成函数求<锡,兜售>在运行时,如果需要,执行



这示出了差可以在这个问题其中OP想做的事一个LINQ到SQL Server中的SQL查询的一部分,把物体进入托管代码,并执行查询的其余部分的LINQ to对象。要实现这一切,他所要做的就是投下的IQueryable到一个IEnumerable他想要切换的情况发生。


Below are two queries that return the same data. Other then style I am not sure which is better.

What factors influence these queries? What are the benefits of using one style over the other?

Sample 1

var x = from s in db.Surveys
    join sq in db.Survey_Questions on s.ID equals sq.Survey_ID
    join q in db.Questions on sq.Question_ID equals q.ID
    join qg in db.Question_Groups on q.ID equals qg.Question_ID
    where s.Type_ID.Equals(typeID) & s.Type.Equals(type)
    select new { question = sq.Question, status = sq.Status, grp = qg };

Sample 2

var x = db.Surveys.Where(s => s.Type_ID.Equals(typeID) & s.Type.Equals(type))
              .Join(db.Survey_Questions,
                        s => s.ID,
                        sq => sq.Survey_ID,
                        (s, sq) => new
                        {
                            question = sq.Question,
                            status = sq.Status
                        })
              .Join(db.Question_Groups,
                        q => q.question.ID,
                        qg => qg.Question_ID,
                        (q, qg) => new
                        {
                            question = q.question,
                            status = q.status,
                            group = qg
                        }).ToList();

解决方案

Update: You have fixed your title, so ignore the rant.

The title of your question has nothing to do with your code samples. Your question implies that one syntax is IEnumerable and the other is IQueryable, but this is incorrect. In your samples, if db.Surveys is an IQueryable, then both your samples are using IQueryable. I will try to answer both questions.

Your two code samples are just different ways of writing the same LINQ queries (assuming they are well-written). The code in sample 1 is just shorthand for the code in sample 2. The compiler treats the code in both samples the same way. Think of the way the C# compiler will treat int? the same as Nullable<System.Int32>. Both the C# and VB.Net languages provide this shorthand query syntax. Other languages might not have this syntax and you would have to use the sample 2 syntax. In fact, other languages might not even support extension methods or lambda expressions, and you would have to use an uglier syntax yet.


Update:

To take Sander's example further, when you write this (query comprehension syntax):

var surveyNames = from s in db.Surveys select s.Name

You think the compiler turns that shorthand into this (extension methods and lambda expression):

IQueryable<string> surveryNames = db.Surveys.Select(s => s.Name);

But actually extension methods and lambda expressions are shorthand themselves. The compilers emits something like this (not exactly, but just to give an idea):

Expression<Func<Survey, string>> selector = delegate(Survey s) { return s.Name; };
IQueryable<string> surveryNames = Queryable.Select(db.Surveys, selector);

Note that Select() is just a static method in the Queryable class. If your .NET language did not support query syntax, lambdas, or extension methods, that is kinda how you would have to write the code yourself.


What are the benefits of using one style over the other?

For small queries, extension methods can be more compact:

var items = source.Where(s => s > 5);

Also, the extension method syntax can be more flexible, such as conditional where clauses:

var items = source.Where(s => s > 5);

if(smallerThanThen)
    items = items.Where(s => s < 10);
if(even)
    items = items.Where(s => (s % 2) == 0);

return items.OrderBy(s => s);

In addition, several methods are only available through extension method syntax (Count(), Aggregate(), Take(), Skip(), ToList(), ToArray(), etc), so if I'll use one of these, I'll usually write the whole query in this syntax to avoid mixing both syntaxes.

var floridaCount = source.Count(s => s.State == "FL");

var items = source
            .Where(s => s > 5)
            .Skip(5)
            .Take(3)
            .ToList();

On the other hand, when a query gets bigger and more complex, query comprehension syntax can be clearer, especially once you start complicating with a few let, group, join, etc.

In the end I will usually use whichever works better for each specific query.


Update: you fixed your title, so ignore the rest...

Now, about your title: With respect to LINQ, IEnumerable and IQueryable are very similar. They both have pretty much the same extension methods (Select, Where, Count, etc), with the main (only?) difference being that IEnumerable takes Func<TIn,TOut> as paremeters and IQueryable takes Expression<Func<TIn,TOut>> as parameters. You express both the same way (usually lamba expressions), but internally they are completely different.

IEnumerable is the doorway to LINQ to Objects. The LINQ to Objects extension methods can be called on any IEnumerable (arrays, lists, anything you can iterate with foreach) and the Func<TIn,TOut> is converted to IL at compile time and runs like a normal method code at run time. Note that some other LINQ providers use IEnumerable and so are actually using LINQ to Objects behind the scenes (LINQ to XML, LINQ to DataSet).

IQueryable is used by LINQ to SQL, LINQ to Entities, and other LINQ providers which need to examine your query and translate it instead of executing your code directly. IQueryable queries and their Expression<Func<TIn,TOut>>s are not compiled into IL at compile time. Instead an expression tree is created and can be examined at run time. This allows the statements to be translated into other query languages (for example T-SQL). An expression tree can be compiled into a Func<TIn,TOut> at run time and executed if desired.

An example that illustrates the difference can be found in this question where the OP wants to do part of a LINQ to SQL query in SQL Server, bring the objects into managed code, and do the rest of the query in LINQ to Objects. To achieve this all he has to do is cast the IQueryable into an IEnumerable where he wants the switch to happen.

这篇关于什么是LINQ查询表达式和扩展方法之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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