繁体   English   中英

什么是EF重写规则?

[英]What are the EF Rewrite Rules?

当使用DBContext编写LINQ查询语法表达式时,C#编译器会使用其18个转换/术语重写规则列表将其查询语法转换为点/扩展语法 然后,当执行查询时,EF应用其自己的内部重写规则来生成SQL表达式。

就像我上面链接的文章一样,我想要列出EF正在应用的重写规则。 我在哪里可以找到它? 如果我知道EF重写规则,我可以预测SQL EF将为给定查询生成什么,而不必等到运行时“看到”生成的SQL。

例如,请考虑以下两个查询:

var result = from c in context.Customers
             from a in c.Accounts
             where c.ID > 2
             select a;

var result = from c in context.Customers
             where c.ID > 2
             from a in c.Accounts
             select a;

当C#编译器完成自己的重写规则时,上述查询将转换为带有以下各种格式的点表示法:

SelectMany(...).Where(...).Select(...); //for the first query

Where(...).SelectMany(...); // for the second query

在这些转换之后,EF开始应用自己的重写规则。 但是EF对于上述两个查询都有一个标准化形式。 换句话说,两个查询都会产生相同的结果; 任一查询都会生成以下SQL语句:

SELECT 
    [Extent1].[ID] AS [ID], 
    [Extent1].[Name] AS [Name], 
    [Extent1].[Stat_ID] AS [Stat_ID]
    FROM  [dbo].[Customers] AS [Extent1]
    INNER JOIN [dbo].[Accounts] AS [Extent2] ON [Extent1].[ID] = [Extent2].[Customer_ID]
    WHERE [Extent2].[ID] > 2

在不知道EF重写规则的情况下,我无法预测到这一点。 我只需要执行和调试代码来进行观察。

那么,我在哪里可以找到EF正在应用的重写规则列表?

我也很好奇EF应用规则的实施策略。 这是一篇讨论几种重写规则策略的文章。 也许我可以通过研究EF源代码来发现这一点,但我正在做的,但我还没有。

遗憾的是,将linq表达式转换为SQL非常复杂,可能不那么容易分成一组简单的离散规则。

例如,linq GroupByJoin东西不倾向于将一对一映射到SQL关键字的同名,因为它们在linq中的行为与在SQL中的行为略有不同(linq GroupBy返回组中的所有项而不仅仅是aggregate和linq Join更像是SQL Server CROSS APPLY )。 实际转换在很大程度上取决于在查询结束时选择的内容,这意味着您通常必须处理整个表达式,而不是简单地将linq方法映射到SQL关键字。

非常值得阅读Matt Warrens关于构建linq提供者的文章http://blogs.msdn.com/b/mattwar/archive/2008/11/18/linq-links.aspx 它可能不是EF正在做的事情,但是让您了解将linq表达式转换为sql所涉及的步骤以及所涉及的复杂性。

一切都取决于数据库连接器,例如,如果要查看SQL Server的生成规则,可以查看EF源 但我不建议您继续使用此规则,它们可能会在下一版本中更改。 我使用MySql和更新连接器3次,每次我遇到EF生成不同查询的问题。 例如表达式:

    .Where(p => new List<int> {1, 2}.Contains(p.value))

在6.5.4中生成为:

   WHERE 1 = `value` OR 2 = `value`

并在6.7.4中生成:

   WHERE `value` IN (1, 2)

PS如果要查看MySql的生成规则,请检查MySql.Data.Entities源

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM