簡體   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