linq groupjoin不会生成预期的sql

时间:2017-04-28 04:19:17

标签: c# linq entity-framework-core

我目前无法从Microsoft.EntityFrameworkCore版本1.1.1获得预期结果。

Tables definition

目前有 Id = 1 的故事,其中有0票。我试图让GroupJoin返回一个对象,如果没有投票,Story对象不为空,Votes列表为空或为空(我认为它将是空)

我在c#中提出了这个查询:

var storyVotes = await StoriesDbContext.Stories.GroupJoin(StoriesDbContext.Votes,
                                                          s => s.Id,
                                                          v => v.StoryId,
                                                          (s, v) => new { Story = s, Votes = v })
                                                          .Where(dict => dict.Story.Id == storyId && (dict.Votes == null || dict.Votes.Any(vo => vo.UserId == userId)))
                                                          .FirstOrDefaultAsync();

编辑:正如Christos指出的那样,上面的C#没有编译。我发布代码时出现了编辑错误。以上现在正确代表代码,结果仍然相同。

在这种情况下,

storyVotes为空。我有点困惑。

linqpad results

LinqPad返回我期望的结果。它返回Story对象和一个列表(包含0个项目)。

我直接在DB上运行的查询也会返回结果。

SELECT s."Id" as StoryId, v."Id" as VoteId
FROM "Stories" s
left outer JOIN "Votes" v on s."Id" = v."StoryId"
WHERE v."UserId" = 'fa157323-c4b2-4d8a-b7fc-c38988405f61' or v."UserId" is null
and s."Id" = 1;

pgadmin 3 results

根据Application Insights,EF生成此查询

SELECT "s"."Id", "s"."CreatedDate", "s"."Description", "s"."DescriptionMarkdown", "s"."ModifiedDate", "s"."Score", "s"."Title", "s"."Upvotes", "s"."Url", "s"."UserId", "s"."UserIsAuthor", "v"."Id", "v"."CommentId", "v"."CreatedDate", "v"."ModifiedDate", "v"."StoryId", "v"."UserId"
FROM "Stories" AS "s"
LEFT JOIN "Votes" AS "v" ON "s"."Id" = "v"."StoryId"
WHERE "s"."Id" = @__storyId_0
ORDER BY "s"."Id"

似乎没有考虑到where子句的&& (dict.v == null || dict.v.Any(vo => vo.UserId == userId)部分。

你能解释为什么会这样,并解释我如何才能达到我想要的结果吗?

1 个答案:

答案 0 :(得分:1)

我认为这个

dict.v == null || dict.v.Any(vo => vo.UserId == userId

应该改为

dict.Votes == null || dict.v.Any(vo => vo.Votes.UserId == userId)

(正如您已为dict.Story所做的那样)。老实说,我想知道为什么编译器没有告知第一个不正确。 v来自哪里?您可以对分组的项目进行投影,每个投影都有两个属性StoryVotes。那里v来自哪里?我不清楚。

关于LINQPad,请注意您的投影有两个属性...... sv ......

<强>更新

通过在LINQPad中仔细查看您的查询,我注意到了

dict.v.Any(vo => vo.Votes.Id == 1)

改变了事情!在查询中,您提到相应的谓词存在问题:

dict.Votes.Any(vo => vo.UserId == userId)

所以你比较两个不同查询的结果。