Linq查询带有Join,没有返回正确的结果

时间:2009-12-19 05:13:06

标签: linq linq-to-objects

我有以下代码,它编译但没有检索到正确的结果。

我正在尝试为在游戏服务器上作弊时录制的人检索所有禁止的日志条目。

数据库(在本例中为两个IList表)有两个简单的

  • GameFiles:游戏中有一个我们解析的日志文件。
  • LogEntries:日志文件中的单个条目。每个游戏文件都有母桶加载的日志条目。

所以这是一个简单的1对多关系。

目前它正在检索GameType.BattleField2的所有结果,但不是GameType.CallOfDuty4的结果。我已经确认IList gameFiles确实包含GameType.BattleField2和GameType.CallOfDuty4的一些数据。我还确认每个文件都有日志条目。

那么,有人可以看看这个linq并告诉我我做错了什么吗?

public IList<LogEntry> BannedEntries(GameType? gameType)
{
    var query = from l in _logEntryRepository.GetLogEntries()
                join g in _gamefileRepository.GetGameFiles()
                on l.GameFileId equals g.GameFileId into JoinedResult
                from x in JoinedResult.DefaultIfEmpty()
                select new 
                { 
                    LogEntry = l,
                    GameFile = x
                };

    if (gameType.HasValue)
    {
        query = from q in query
                where q.GameFile.GameType == gameType
                select q;
    }

    // Now retrieve only LogEntries.
    return (from q in query
            where q.LogEntry.EventType == EventType.BannableViolation
            select q.LogEntry)
            .ToListIfNotNullOrEmpty();
}

1 个答案:

答案 0 :(得分:0)

鉴于您需要日志,请尝试使用这个简化的仅用于演示的代码:

string optionalGameType = "COD4";
//retrieve log entries for BANNED, with optional specified game type
List<LogFile> banned = logs.Where(x => x.EventType == "banned")
                 .WhereIf(optionalGameType.Length > 0, (x => x.GameFileID == games.Where(g => g.GameType == optionalGameType).SingleOrDefault().GameFileID))
                 .ToList();           

int cod4BannedCount = banned.Count;

return banned;

我使用的是字符串而不是您的自定义类型,而是使用字符串而不是EventType.BannableViolation。您可以轻松使用自定义类型。

full source/proof is at this pastebin page

查看WhereIf extension method。它帮助我几次避免这些条件作为单独的陈述。

鉴于该示例,您的代码可能会被重构为如下所示:

List<LogEntry> banned = _logEntryRepository.GetLogEntries()
                .Where(x => x.EventType == EventType.BannableViolation)
                .WhereIf(gameType.HasValue,
                    (x => x.GameFile.GameType == _gamefileRepository.GetGameFiles()
                                         .Where(g => g.GameType == gameType) 
                                         .SingleOrDefault()
                                         .GameType
                     ))
                 .ToList();