0

我有一个带有以下类的实体框架模型(我已经简化了这些类以便于查看):

 PuzzleItem
 -PuzzleId (int, primary key)
 -Title

 PuzzleProgress
 -ProgressId (int, primary key)
 -PuzzleId (FK)
 -UserId (FK)

PuzzleItem我有许多级别。当PuzzleProgress用户完成上一个级别时,通过插入该级别的记录来跟踪用户处于哪个级别。PuzzleProgress首先,新用户将有一个条目PuzzleId = 1

在我的代码中,我使用以下语句执行左外连接,这样我将获得所有谜题的列表,并向我指出哪个谜题尚未解决。我从 StackOverflow参考了这篇文章。

这是我的代码:

var result = from pzs in e.PuzzleItems
                         join prg in e.PuzzleProgresses on pzs equals prg.PuzzleItem
                         into pzs_prg_tbl
                         from pzs_prg in pzs_prg_tbl.DefaultIfEmpty()
                         where pzs_prg.UserId == userId
                         select new SimplePuzzleItem()
                         {
                             PuzzleId = pzs_prg.PuzzleId,
                             PuzzleName = pzs_prg.PuzzleItem.Title,
                             IsUnlocked = (pzs_prg == null?false:true)
                         };

运行代码后,只返回这个新用户的第一级(而PuzzleItem表有3条记录)。

我试过玩代码,但我上面粘贴的代码是我能到达的最近的,有人能指出我正确的方向吗?谢谢!

4

2 回答 2

4

在没有看到更多代码的情况下很难准确地说出来,但where pzs_prg.UserId == userId可能会否定左外连接。

我的意思是,如果您打算这样做,PuzzleItems LEFT JOIN PuzzleProgress那么即使没有 PuzzleProgress,您也需要所有 PuzzleItems。但where pzs_prg.UserId == userIdPuzzleProgress 的意思不能为 null,因为它必须有一个 UserId(值为 userId)。所以,你实际上有一个内部连接。

就个人而言,我不喜欢在 linq 中进行连接(左或内)的“正确”方式,所以这就是我更正 linq 语句的方式:

        var result = from pz in db.PuzzleItems
                     from pg in db.PuzzleProgresses
                                  .Where(pg => pg.PuzzleId == pz.PuzzleId)
                                  .Where(pg => pg.UserId == userId)
                                  .DefaultIfEmpty()
                     select new
                                {
                                    PuzzleId = pz.PuzzleId,
                                    PuzzleName = pz.Title,
                                    IsUnlocked = (pg != null)
                                };

这读起来更像是 SQL 连接,这是我很久以前学过的,所以它符合我的想法。

如果您想重构连接类型语法,请查看此'LINQ Joining in c# with multiple conditions'

于 2013-03-25T17:47:57.953 回答
1

我认为 where 子句正在过滤掉记录。您需要在左连接中包含 where 子句。像这样:

var result = from pzs in e.PuzzleItems
             join prg in e.PuzzleProgresses on new { pzs.PuzzleId, UserId = userId } equals new { prg.PuzzleId, prg.UserId }
             into pzs_prg_tbl
             from pzs_prg in pzs_prg_tbl.DefaultIfEmpty()
             select new SimplePuzzleItem()
             {
               PuzzleId = pzs_prg.PuzzleId,
               PuzzleName = pzs_prg.PuzzleItem.Title,
               IsUnlocked = (pzs_prg == null?false:true)
             };
于 2013-03-25T17:37:46.947 回答