Linq-to-entities中的OrderBy、Select和Where子句的顺序是否重要?

7
假设我有一张包含大量列的学生表。我想要EF的等效操作:
SELECT id,lastname,firstname 
FROM students 
WHERE coursename='Eurasian Nomads'
ORDER BY lastname,firstname

我只想使用Student模型的一个子集,因此我创建了一个视图模型。

public class StudentView{
    public int ID{get;set;}
    public string LastName{get;set;}
    public string FirstName{get;set;}
}

这段 EF 代码似乎可以工作:

List<StudentView> students=context.Students
.Where(s=>s.CourseName=="Eurasian Nomads")
.OrderBy(s=>s.LastName)
.ThenBy(s=>s.FirstName)
.Select(s=>new StudentView(){ID=s.ID,LastName=s.LastName,FirstName=s.FirstName})
.ToList();

但我的问题是这些子句的顺序是否很重要,如果是的话,我应该遵循什么样的规则以获得最佳性能?

例如,以下语句似乎也可以工作:

List<StudentView> students=context.Students
.Select(s=>new StudentView(){ID=s.ID,LastName=s.LastName,FirstName=s.FirstName})
.OrderBy(s=>s.LastName)
.ThenBy(s=>s.FirstName)
.Where(s=>s.CourseName=="Eurasian Nomads")
.ToList();

我会让其他人发布一个完整的答案,但是顺序并不重要,因为所有的方法都返回一个 IQueryable 对象,并且查询的执行实际上被推迟到可能的最后一刻,在你的情况下是当你调用 ToList 时。 - Louis
2
如果您正在使用SQL Server,则可以使用SQL Profiler查看每个变体生成的SQL查询以及每个查询所需的时间。如果我必须猜测,我会说它们是相同的。 - Yacoub Massad
3
选择很重要,因为它会将你的IQueryable类型从一种形式变成另一种形式。OrderByWhere不应该影响结果。 - Max
在这里,特定的顺序似乎并不重要,但是从一般意义上讲,在linq-to-entities中顺序肯定会产生影响。 - stephen.vakil
1个回答

4
在大多数情况下,您创建查询的顺序在执行之前并不重要。实际上,其中一个优点是能够通过连接where、order by和其他子句逐步创建查询。
但有时候顺序可能会影响生成的SQL语句。
以您提供的示例为例。它们都可以正确编译,但第二个实际上不会被执行。如果您尝试在EF数据库中运行此查询,您将得到一个NotSupportedException异常:
System.NotSupportedException: The specified type member 'CourseName' is not supported in LINQ to Entities.

关键在于您试图通过视图模型(StudentView)中的CourseName属性而不是实体的属性来过滤查询。因此,您会收到此错误消息。
对于第一个查询,它正确地生成了这个SQL语句:
SELECT
    [Extent1].[ID] AS [ID],
    [Extent1].[LastName] AS [LastName],
    [Extent1].[FirstName] AS [FirstName]
    FROM [dbo].[Students] AS [Extent1]
    WHERE N'Eurasian Nomads' = [Extent1].[CourseName]
    ORDER BY [Extent1].[LastName] ASC, [Extent1].[FirstName] ASC

所以,正如您所看到的,有时候顺序非常关键。

2
这是一个很好的解释。我认为值得补充的是,NotSupportedException是因为Select将查询转换为StudentView查询,而不是Student查询,而StudentView不包含CourseName属性。 - Max
2
确实,@Max。这就是我所说的“关键在于你试图通过视图模型中的CourseName属性来过滤查询”的意思,但我认为你的澄清肯定是有效的。谢谢。 - Karel Tamayo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接