Linq-запрос с Join, не возвращающий правильные результаты - PullRequest
1 голос
/ 19 декабря 2009

У меня есть следующий код, который компилируется, но не возвращает правильные результаты.

Я пытаюсь получить все записи журнала Banned для людей, которые были зарегистрированы в мошенничестве на игровом сервере.

База данных (в данном случае две таблицы IList) содержит две простые таблицы .

  • GameFiles: игра, в которой есть лог-файл .. который мы анализируем.
  • LogEntries: отдельная запись в файле журнала. Каждый игровой файл имеет загрузку записей журнала.

Так что это простые отношения 1 ко многим.

В настоящее время он получает все результаты для GameType.BattleField2, но не для GameType.CallOfDuty4. Я подтвердил, что игровые файлы IList содержат некоторые данные для 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 голосов
/ 19 декабря 2009

Учитывая, что вам нужны журналы, попробуйте этот упрощенный для демонстрации код:

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. Вместо этого вам будет легко использовать ваши пользовательские типы.

Полный исходный код / ​​подтверждение находится на этой странице вставки .

Проверьте метод расширения WhereIf . Несколько раз мне помогло избежать этих условных выражений в виде отдельных утверждений.

Учитывая этот пример, ваш код может быть изменен, чтобы выглядеть примерно так:

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();
...