简体   繁体   English

什么是EF重写规则?

[英]What are the EF Rewrite Rules?

When a LINQ query syntax expression is written with DBContext, the C# compiler does its usual magic of converting the query syntax into dot / extension syntax using its list of 18 transformation / term rewrite rules . 当使用DBContext编写LINQ查询语法表达式时,C#编译器会使用其18个转换/术语重写规则列表将其查询语法转换为点/扩展语法 Then when the query is executed, EF applies its own internal rewrite rules to produce a SQL expression. 然后,当执行查询时,EF应用其自己的内部重写规则来生成SQL表达式。

Just like the article I linked above, I'd like to have a list of the rewrite rules that EF is applying. 就像我上面链接的文章一样,我想要列出EF正在应用的重写规则。 Where can I find that? 我在哪里可以找到它? If I know the EF rewrite rules, I can predict what SQL EF will generate for a given query, instead of having to wait until run-time to "see" the generated SQL. 如果我知道EF重写规则,我可以预测SQL EF将为给定查询生成什么,而不必等到运行时“看到”生成的SQL。

For example, consider the following two queries: 例如,请考虑以下两个查询:

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;

When the C# compiler finishes its own rewrite rules, the above queries are transformed into dot-notation with the following respective formats: 当C#编译器完成自己的重写规则时,上述查询将转换为带有以下各种格式的点表示法:

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

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

After these conversions, EF gets to work applying its own rewrite rules. 在这些转换之后,EF开始应用自己的重写规则。 But EF has a single normalized form for both of the above queries. 但是EF对于上述两个查询都有一个标准化形式。 In other words, both queries will produce identical results; 换句话说,两个查询都会产生相同的结果; either query generates the following SQL statement: 任一查询都会生成以下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

Without knowing the EF rewrite rules, I could not have predicted that. 在不知道EF重写规则的情况下,我无法预测到这一点。 I simply had to execute and debug code to make that observation. 我只需要执行和调试代码来进行观察。

So again, where can I find a list of the rewrite rules that EF is applying? 那么,我在哪里可以找到EF正在应用的重写规则列表?

I am also curious what implementation strategy EF has for applying the rules. 我也很好奇EF应用规则的实施策略。 Here is an article discussing several rewrite rule strategies . 这是一篇讨论几种重写规则策略的文章。 Perhaps I could discover this by studying the EF source code but, which I am doing, but I'm not there yet. 也许我可以通过研究EF源代码来发现这一点,但我正在做的,但我还没有。

Converting linq expression into SQL is unfortunately very complicated and is probably not so easily split into a set of simple discrete rules. 遗憾的是,将linq表达式转换为SQL非常复杂,可能不那么容易分成一组简单的离散规则。

For example things such as linq GroupBy and Join don't tend to map one to one to the SQL keywords by the same name as they behave slightly differently in linq as they do in SQL (linq GroupBy returns all items in the group rather than just aggregates and linq Join is more like SQL Server CROSS APPLY ). 例如,linq GroupByJoin东西不倾向于将一对一映射到SQL关键字的同名,因为它们在linq中的行为与在SQL中的行为略有不同(linq GroupBy返回组中的所有项而不仅仅是aggregate和linq Join更像是SQL Server CROSS APPLY )。 The actual transformation depends highly on what is selected out at the end of the query, meaning you usually have to process the whole expression rather than a simple mapping of linq method to SQL keyword. 实际转换在很大程度上取决于在查询结束时选择的内容,这意味着您通常必须处理整个表达式,而不是简单地将linq方法映射到SQL关键字。

It is well worth reading Matt Warrens articles on building a linq provider http://blogs.msdn.com/b/mattwar/archive/2008/11/18/linq-links.aspx . 非常值得阅读Matt Warrens关于构建linq提供者的文章http://blogs.msdn.com/b/mattwar/archive/2008/11/18/linq-links.aspx It may not be exactly what EF is doing but gives you an idea of what steps are involved in converting linq expression to sql and the complexities involved. 它可能不是EF正在做的事情,但是让您了解将linq表达式转换为sql所涉及的步骤以及所涉及的复杂性。

Everything depends on database connector, for example if you want to see generation rules for SQL server, you can look at EF sources . 一切都取决于数据库连接器,例如,如果要查看SQL Server的生成规则,可以查看EF源 But i won't recommend you to relay on this rules, they might change in next version. 但我不建议您继续使用此规则,它们可能会在下一版本中更改。 I work with MySql and updated connector 3 times and every time i am facing problem that EF generates different queries and. 我使用MySql和更新连接器3次,每次我遇到EF生成不同查询的问题。 For example expression: 例如表达式:

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

in 6.5.4 generated as: 在6.5.4中生成为:

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

And in 6.7.4 generated as: 并在6.7.4中生成:

   WHERE `value` IN (1, 2)

PS if you want to see generation rules for MySql, check MySql.Data.Entities sources PS如果要查看MySql的生成规则,请检查MySql.Data.Entities源

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

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