背景:在接下来的一个月里,我将做三次关于LINQ的演讲,或者至少将LINQ包含在c#的上下文中。我想知道哪些话题值得花相当多的精力,这取决于人们可能很难理解哪些话题,或者他们可能有错误的印象。我不会具体讨论LINQ to SQL或实体框架,只是作为如何使用表达式树(通常是IQueryable)远程执行查询的示例。

那么,你发现LINQ有什么难的地方吗?在误解方面你看到了什么?例子可能是以下任何一个,但请不要限制自己!

c#编译器如何处理查询表达式 Lambda表达式 表达式树 扩展方法 匿名类型 这个IQueryable 延迟执行与立即执行 流与缓冲执行(例如,OrderBy被延迟但被缓冲) 隐式类型局部变量 读取复杂的泛型签名(例如Enumerable.Join)


当前回答

我认为Lambda表达式可以解析表达式树和匿名委托的事实,因此您可以将相同的声明性Lambda表达式传递给IEnumerable<T>扩展方法和IQueryable<T>扩展方法。

其他回答

表达式<Func<T1, T2, T3,…>> and Func<T1, T2, T3,…>,没有给出第二个情况下性能下降的提示。

下面是代码示例,演示了我的意思:

[TestMethod]
public void QueryComplexityTest()
{
    var users = _dataContext.Users;

    Func<User, bool>                funcSelector =       q => q.UserName.StartsWith("Test");
    Expression<Func<User, bool>>    expressionSelector = q => q.UserName.StartsWith("Test");

    // Returns IEnumerable, and do filtering of data on client-side
    IQueryable<User> func = users.Where(funcSelector).AsQueryable();
    // Returns IQuerible and do filtering of data on server side
    // SELECT ... FROM [dbo].[User] AS [t0] WHERE [t0].[user_name] LIKE @p0
    IQueryable<User> exp = users.Where(expressionSelector);
}

我花了很长时间才意识到许多LINQ扩展方法,如Single(), SingleOrDefault()等都有重载,使用lambdas。

你可以:

Single(x => x.id == id)

我不需要这么说——一些糟糕的教程让我养成了这样做的习惯

Where(x => x.id == id).Single()

延迟加载。

我发现查询表达式语法只支持LINQ功能的一个子集,这有点令人失望,因此您无法避免时不时地链接扩展方法。例如,Distinct方法不能使用查询表达式语法调用。要使用Distinct方法,需要调用扩展方法。另一方面,查询表达式语法在许多情况下非常方便,所以您也不想跳过它。

关于LINQ的演讲可以包括一些实用的指导方针,比如什么时候更喜欢一种语法而不是另一种,以及如何混合使用它们。

对于LINQ2SQL:熟悉一些生成的SQL并编写可以转换为良好(快速)SQL的LINQ查询。这是知道如何平衡LINQ查询的声明性和它们需要在已知环境(SQL Server)中快速执行的真实性这一更大问题的一部分。

你可以得到一个完全不同的SQL生成查询通过改变一个很小很小的东西在LINQ代码。如果您正在基于条件语句创建表达式树(即添加可选的过滤条件),这可能特别危险。