最近在做項目使用linq結合EntityFramework來處理數據庫的操作。想來也用了快一年了,發現有些使用技巧是需要注意下,特做下總結,希望對剛入門的朋友們有所幫助。剛開始用的時候各總循環查詢子查詢,結果性能差得不行,現在看看都覺得好笑。也只有寫出過很爛的代碼才知道怎么樣的代碼才是優雅的吧,哈哈。我先總結下連接查詢吧,發現很多剛入門的朋友和我一樣,不知道怎么用linq寫類似與sql的連接查詢(left join、inner join等等)。
連接查詢
-
內連接查詢
linq語法如下:
1 var res = from a in sys.Apple 2 join b in sys.Banana 3 on a.Id equals b.AppleId 4 select new { 5 a.Id, 6 a.Name 7 };
直接寫join就是內連接查詢,我們來看看它生產的sql語句就明白為什么這是內連接了。
生成的sql如下:
SELECT 1 AS [C1], [Extent1].[Id] AS [Id], [Extent1].[Name] AS [Name] FROM [dbo].[apple] AS [Extent1] INNER JOIN [dbo].[banana] AS [Extent2] ON [Extent1].[Id] = [Extent2].[AppleId]
-
左連接、右連接
左連接linq語法如下:
1 var res = from a in sys.Apple 2 join b in sys.Banana 3 on a.Id equals b.AppleId into b1 4 select new { 5 a.Id, 6 a.Name, 7 Bananas = b1 8 };
這里的關鍵在於第7行的集合賦值哦,EF會根據你需要查詢的結果生成相應的sql語句。
來看下生成的sql語句吧:

SELECT [Project1].[C1] AS [C1], [Project1].[Id] AS [Id], [Project1].[Name] AS [Name], [Project1].[C2] AS [C2], [Project1].[Id1] AS [Id1], [Project1].[Name1] AS [Name1], [Project1].[AppleId] AS [AppleId], [Project1].[comment] AS [comment] FROM ( SELECT [Extent1].[Id] AS [Id], [Extent1].[Name] AS [Name], 1 AS [C1], [Extent2].[Id] AS [Id1], [Extent2].[Name] AS [Name1], [Extent2].[AppleId] AS [AppleId], [Extent2].[comment] AS [comment], CASE WHEN ([Extent2].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C2] FROM [dbo].[apple] AS [Extent1] LEFT OUTER JOIN [dbo].[banana] AS [Extent2] ON [Extent1].[Id] = [Extent2].[AppleId] ) AS [Project1] ORDER BY [Project1].[Id] ASC, [Project1].[C2] ASC
這個查詢的結果會是一個對象包含b1結合,而不是sql的查詢到的連接后的臨時表結果。這里是EF自動幫我們把數據整理這樣的形式了。在查詢一對多的表數據時是很有用的哦。當然也可以用導航屬性啦。
來看看另一形式的左連接吧
linq語法如下:
1 var res = from a in sys.Apple 2 join b in sys.Banana 3 on a.Id equals b.AppleId into b1 4 from b2 in b1.DefaultIfEmpty() 5 select new { 6 a.Id, 7 a.Name, 8 t = b2.AppleId 9 };
生成的sql語句:
SELECT 1 AS [C1], [Extent1].[Id] AS [Id], [Extent1].[Name] AS [Name], [Extent2].[AppleId] AS [AppleId] FROM [dbo].[apple] AS [Extent1] LEFT OUTER JOIN [dbo].[banana] AS [Extent2] ON [Extent1].[Id] = [Extent2].[AppleId]
這樣查詢的結果的集合數據就和笛卡爾積后的臨時表的行數是對應的了。在一對多的的情況下主表的數據會被重復哦。
右連接只要把 apple 和banana的順序對調下就是了哦。
總結一下吧EF生成的sql語句是很靈活的,select的內容對最后生成的inner join還是left join的影響是很大的。以上寫法僅供參考,當然左連接、右連接還有其他的寫法。
-
全連接
那全連接怎么寫呢,有點意外,其實很簡單。
linq語法如下:
var res = from a in sys.Apple from b in sys.Banana select new { a.Id, a.Name, //Bananas = b1 t = b.AppleId };
生成的sql語句:
SELECT 1 AS [C1], [Extent1].[Id] AS [Id], [Extent1].[Name] AS [Name], [Extent2].[AppleId] AS [AppleId] FROM [dbo].[apple] AS [Extent1] CROSS JOIN [dbo].[banana] AS [Extent2]
到這里就把連接查詢介紹完了。在對多表進行查詢的時候,連接查詢應用的地方是很多的。提醒大家在查詢多個表的時候,切忌使用foreach 或是 select里面寫子查詢,盡量用連接查詢來替代。從我的實踐來看大多數情況下連接查詢的效率要比循環子查詢高得多。甚至是10倍以上的差距。