如何以及何时翻译和评估LINQ查询?

时间:2013-01-04 11:15:42

标签: c# asp.net sql linq lambda

我有一个LINQ to SQL Query,如下所示:

var carIds = from car in _db.Cars
           where car.Color == 'Blue'
           select car.Id;

以上将最终翻译成以下的SQL:

select Id from Cars 
where Color = 'Blue'

我读过这些阶段是:

  1. LINQ to Lambda Expression
  2. Lambda Expression to Expression Trees
  3. 表达式树到SQL语句
  4. 执行SQL语句
  5. 所以,我的问题是何时以及如何翻译和执行?

    我知道第4阶段是在运行时在foreach循环中访问我的“carIds”变量时发生的。

    foreach(var carId in carIds) // here?
    {
      Console.Writeline(carId) // or here?
    }
    

    其他阶段呢?他们什么时候发生?在编译时或运行时?在哪一行(在定义上或定义之后,在访问时或在访问之前)?

2 个答案:

答案 0 :(得分:3)

你所谈论的是 延迟执行 - 本质上,linq to SQL查询将在你尝试枚举结果时执行(例如迭代它,。ToArray()等)。

在您的示例中,语句在以下行执行:

foreach(var carId in carIds)

请参阅LINQ and Deferred Execution

上的这篇MSDN文章

答案 1 :(得分:2)

  1. 由您,开发人员或C#编译器完成;您可以手动编写lambda表达式,或者使用LINQ语法,可以从LINQ隐含它们(即where x.Foo == 12被视为.Where(x => x.Foo == 12),然后编译器根据它处理第2步)
  2. 由C#编译器完成;它翻译了" lambda表达式"在IL中构造(或在可能的情况下重用)表达式树。您还可以说运行时是进程此步骤
  3. 通常在查询枚举时完成,特别是在foreach调用GetEnumerator()时(甚至可能推迟到第一个.MoveNext
  4. 延迟执行允许查询撰写;例如:

    var query = ...something complex...
    var items = query.Take(20).ToList();
    

    此处Take(20)作为整体查询的一部分执行,因此您不会从服务器和然后(在调用者)将其过滤到前20个;从服务器中只检索到20行。

    您还可以使用编译查询将查询限制为仅执行步骤4(或者在某些情况下,根据参数需要不同的TSQL,步骤3和4)。或者如果您只编写TSQL,则可以跳过除4之外的所有内容。

    你还应该添加一个步骤" 5":实现;这是一个非常复杂而重要的步骤。根据我的经验,在整体表现方面,实现步骤实际上可以是 最重要的 (因此我们为什么写了" dapper")。