[英]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 GroupBy
和Join
東西不傾向於將一對一映射到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.