我目前无法从Microsoft.EntityFrameworkCore
版本1.1.1获得预期结果。
目前有 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返回我期望的结果。它返回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;
根据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)
部分。
你能解释为什么会这样,并解释我如何才能达到我想要的结果吗?
答案 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
来自哪里?您可以对分组的项目进行投影,每个投影都有两个属性Story
和Votes
。那里v
来自哪里?我不清楚。
关于LINQPad,请注意您的投影有两个属性...... s
和v
......
<强>更新强>
通过在LINQPad中仔细查看您的查询,我注意到了
dict.v.Any(vo => vo.Votes.Id == 1)
改变了事情!在查询中,您提到相应的谓词存在问题:
dict.Votes.Any(vo => vo.UserId == userId)
所以你比较两个不同查询的结果。