gpt4 book ai didi

c# - LINQ 查询表达式和扩展方法有什么区别

转载 作者:可可西里 更新时间:2023-11-01 08:02:50 25 4
gpt4 key购买 nike

下面是返回相同数据的两个查询。其他风格我不确定哪个更好。

哪些因素会影响这些查询?
使用一种样式比另一种样式有什么好处?

示例 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 };

样本 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();

最佳答案

更新:你已经修正了你的标题,所以忽略咆哮。

您的问题标题与您的代码示例无关。您的问题意味着一种语法是 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

你认为编译器把这个简写变成了这个(扩展方法和 lambda 表达式):
IQueryable<string> surveryNames = db.Surveys.Select(s => s.Name);

但实际上扩展方法和 lambda 表达式本身就是速记。编译器发出这样的东西(不完全是,只是为了提供一个想法):
Expression<Func<Survey, string>> selector = delegate(Survey s) { return s.Name; };
IQueryable<string> surveryNames = Queryable.Select(db.Surveys, selector);

请注意 Select()只是 Queryable 中的一个静态方法类(class)。如果您的 .NET 语言不支持查询语法、lambdas 或扩展方法,那么您将不得不自己编写代码。

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



对于小型查询,扩展方法可以更紧凑:
var items = source.Where(s => s > 5);

此外,扩展方法语法可以更灵活,例如条件 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);

此外,有几种方法只能通过扩展方法语法使用(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();

另一方面,当查询变得更大和更复杂时,查询理解语法可以更清晰,尤其是当您开始用几个 let 复杂化时。 , group , join , 等等。

最后,我通常会使用对每个特定查询更有效的方法。

更新:你修正了你的标题,所以忽略其余的......

现在,关于您的标题:关于 LINQ,IEnumerable 和 IQueryable 非常相似。它们都有几乎相同的扩展方法(Select、Where、Count 等),主要(唯一?)区别在于 IEnumerable 需要 Func<TIn,TOut>作为参数和 IQueryable 需要 Expression<Func<TIn,TOut>>作为参数。您以相同的方式表达(通常是lamba 表达),但在内部它们是完全不同的。

IEnumerable 是 LINQ to Objects 的入口。 LINQ to Objects 扩展方法可以在任何 IEnumerable(数组、列表、任何你可以用 foreach 迭代的东西)和 Func<TIn,TOut> 上调用。在编译时转换为 IL 并在运行时像普通方法代码一样运行。请注意,其他一些 LINQ 提供程序使用 IEnumerable,因此实际上在幕后使用 LINQ to Objects(LINQ to XML、LINQ to DataSet)。

IQueryable 由 LINQ to SQL、LINQ to Entities 和其他 LINQ 提供程序使用,这些提供程序需要检查您的查询并对其进行转换,而不是直接执行您的代码。 IQueryable 查询及其 Expression<Func<TIn,TOut>> s 不会在编译时编译到 IL 中。取而代之的是创建一个表达式树并可以在运行时进行检查。这允许将语句翻译成其他查询语言(例如 T-SQL)。表达式树可以在运行时编译为 Func 并在需要时执行。

可以在 this question 中找到说明差异的示例。 OP 希望在 SQL Server 中执行部分 LINQ to SQL 查询,将对象引入托管代码,并在 LINQ to Objects 中执行其余查询。为了实现这一点,他所要做的就是将 IQueryable 转换为他希望发生切换的 IEnumerable。

关于c# - LINQ 查询表达式和扩展方法有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/796246/

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