Ton*_*ell 14 c# linq query-expressions
下面是两个返回相同数据的查询.除了风格,我不确定哪个更好.
哪些因素会影响这些查询?使用一种风格而不是另一种风格有什么好处?
样品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 };
Run Code Online (Sandbox Code Playgroud)
样本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();
Run Code Online (Sandbox Code Playgroud)
Luc*_*cas 23
更新:你已修复你的标题,所以忽略咆哮.
您的问题标题与您的代码示例无关.你的问题暗示一个语法是IEnumerable而另一个是IQueryable,但这是不正确的.在您的样本中,如果db.Surveys是IQueryable,那么您的两个样本都使用IQueryable.我会尝试回答这两个问题.
您的两个代码示例只是编写相同LINQ查询的不同方式(假设它们编写得很好).示例1中的代码只是示例2中代码的简写.编译器以相同的方式处理两个示例中的代码.想想C#编译器对待它int?的方式Nullable<System.Int32>.C#和VB.Net语言都提供了这种简写查询语法.其他语言可能没有此语法,您必须使用示例2语法.实际上,其他语言甚至可能不支持扩展方法或lambda表达式,您还必须使用更丑陋的语法.
更新:
要进一步采用Sander的例子,当你写这个(查询理解语法)时:
var surveyNames = from s in db.Surveys select s.Name
Run Code Online (Sandbox Code Playgroud)
您认为编译器将该缩写转换为此(扩展方法和lambda表达式):
IQueryable<string> surveryNames = db.Surveys.Select(s => s.Name);
Run Code Online (Sandbox Code Playgroud)
但实际上扩展方法和lambda表达式本身就是简写.编译器发出类似这样的东西(不完全是,但只是为了给出一个想法):
Expression<Func<Survey, string>> selector = delegate(Survey s) { return s.Name; };
IQueryable<string> surveryNames = Queryable.Select(db.Surveys, selector);
Run Code Online (Sandbox Code Playgroud)
请注意,这Select()只是类中的静态方法Queryable.如果您的.NET语言不支持查询语法,lambdas或扩展方法,那么您必须自己编写代码.
使用一种风格而不是另一种风格有什么好处?
对于小型查询,扩展方法可以更紧凑:
var items = source.Where(s => s > 5);
Run Code Online (Sandbox Code Playgroud)
此外,扩展方法语法可以更灵活,例如条件where子句:
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);
Run Code Online (Sandbox Code Playgroud)
另外,有几种方法只能通过扩展方法语法(Count(),Aggregate(),Take(),Skip(),ToList(),ToArray()等)来实现,所以如果我将使用其中一种,我通常会用这种语法编写整个查询,以避免混合使用这两种语法.
var floridaCount = source.Count(s => s.State == "FL");
var items = source
.Where(s => s > 5)
.Skip(5)
.Take(3)
.ToList();
Run Code Online (Sandbox Code Playgroud)
在另一方面,当查询变得更大,更复杂,查询综合语法可以更清晰,特别是一旦你开始有一些复杂let,group,join,等.
最后,我通常会使用哪个更适合每个特定查询.
更新:你修改了你的标题,所以忽略其余的...
现在,关于你的标题:关于LINQ,IEnumerable和IQueryable非常相似.它们都具有几乎相同的扩展方法(Select,Where,Count等),主要(仅?)区别在于IEnumerable Func<TIn,TOut>作为参数,IQueryable Expression<Func<TIn,TOut>>作为参数.你用同样的方式表达(通常是lamba表达式),但在内部却完全不同.
IEnumerable是LINQ to Objects的入口.可以在任何IEnumerable(数组,列表,您可以迭代的任何东西foreach)上调用LINQ to Objects扩展方法,并Func<TIn,TOut>在编译时将其转换为IL,并在运行时像普通方法代码一样运行.请注意,其他一些LINQ提供程序使用IEnumerable,因此实际上在幕后使用LINQ to Objects(LINQ to XML,LINQ to DataSet).
LINQ to SQL,LINQ to Entities和其他LINQ提供程序使用IQueryable,它们需要检查您的查询并转换它而不是直接执行代码.IQueryable查询及其Expression<Func<TIn,TOut>>在编译时不会编译到IL中.而是创建表达式树,并且可以在运行时检查它.这允许将语句翻译成其他查询语言(例如T-SQL).表达式树可以在运行时编译为Func <TIn,TOut>,并在需要时执行.
在这个问题中可以找到一个示例差异的示例,其中OP希望在SQL Server中执行LINQ to SQL查询的一部分,将对象引入托管代码,并在LINQ to Objects中执行其余查询.要实现这一点,他所要做的就是将IQueryable转换为IEnumerable,他希望切换发生.