我無法將SQL查詢轉換爲適當的EF查詢。我很接近,但我想我錯過了左連接的東西。將查詢從SQL轉換爲EF Lambda表達式
這是我的SQL(略微人爲的例子):
SELECT
Count(*), -- count posts
Tag.Name,
ISNULL(Category.Name, 'Other')
FROM Post
INNER JOIN Tag ON Post.TagID=Tag.ID
LEFT OUTER JOIN Category ON Tag.CategoryID=Category.ID
GROUP BY
Tag.Name, ISNULL(Category.Name, 'Other')
帖子有0-1標籤(就像我說的,稍有人爲的例子)。標籤有0-1個分類。所以INNER
和LEFT
連接很重要。
這是我的不是,相當右EF查詢:
var counts = ctx.Posts
.GroupBy(po =>
new
{
Tag = po.Tag.Name,
Category = po.Tag.Category.Name ?? "Other"
})
.Select(agg =>
new
{
NumberOfPosts = agg.Count(),
Tag = agg.Key.Tag,
Category = agg.Key.Category
})
.ToList();
這EF查詢結果在這個SQL查詢,這是不完全正確:
SELECT
1 AS [C1],
[GroupBy1].[A1] AS [C2],
[GroupBy1].[K1] AS [Name],
[GroupBy1].[K2] AS [C3]
FROM (SELECT
[Join2].[K1] AS [K1],
[Join2].[K2] AS [K2],
COUNT([Join2].[A1]) AS [A1]
FROM (SELECT
[Extent2].[Name] AS [K1],
CASE WHEN ([Extent3].[Name] IS NULL) THEN N'Other' ELSE [Extent3].[Name] END AS [K2],
1 AS [A1]
FROM [dbo].[Post] AS [Extent1]
LEFT OUTER JOIN [dbo].[Tag] AS [Extent2] ON [Extent1].[TagID] = [Extent2].[ID]
LEFT OUTER JOIN [dbo].[Category] AS [Extent3] ON [Extent2].[CategoryID] = [Extent3].[ID]
) AS [Join2]
GROUP BY [K1], [K2]
) AS [GroupBy1]
其中一個連接是不正確。另外,我不確定ISNULL是否由GROUP BY正確處理(這很重要,因爲我希望它將空值和DB中的值與「其他」值一起組合爲一個值) 。
我該如何解決這個問題?或者,這只是其中一種有趣的場景,我需要回退到其他的東西(一個短片或視圖)?
VS2017/C#/。NET4.7/EF6.13/SQLAzure
(編輯補充所得SQL語句)
你的LINQ查詢有什麼問題?對我來說看起來不錯 - 只要你有正確的實體映射,EF應該爲你生成正確的連接(通過導航屬性)。你可以發佈生成的SQL(用'ToString()')替換'ToList()'? –
@IvanStoev有些東西與我的數量有關。我相信這兩個連接都是以'LEFT OUTER'連接的形式進入的,或者兩者都以'INNER'連接的形式進入。我正在處理隨機生成的數據,因此我不太清楚哪些數據,因爲我打了Azure,所以無法使用Profiler來獲取查詢。即使基數相同,我也特別想要兩種不同類型的連接。 – Jaxidian
我明白了。根據你的解釋,最有可能兩個都是'left outer join'('Optional'relatonship)。如何獲得SQL查詢,你不需要一個分析器 - 只是一個調試器(請參閱我以前的評論:)無論如何,沒有辦法強制導航屬性生成不同的連接比指定的關係,所以我想你必須使用一個手動的'join' LINQ查詢來代替'po.Tag'。或者在'GroupBy'之前添加'.Where(po => po.Tag!= null)'。 –