C # LINQ - исключить нулевой объект из результата запроса [EF - No Referential Int] - PullRequest
0 голосов
/ 02 июля 2018

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

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

Мой оригинальный метод решения проблемы приведен ниже, но вот моя основная проблема.

var test1 =
    DbContext.Report
        .Where(x => x.Pupil != null).ToList();

var test2 =
    DbContext.Report
        .Include(x => x.Pupil)
        .Where(x => x.Pupil != null).ToList();

if (test1.Count(x => x.Pupil == null) > 0)
{
    var bp = "hit"; // I know this doesn't work
}

if (test2.Count(x => x.Pupil == null) > 0)
{
    var bp = "hit"; // But why doesn't this? And how can I make it work...
}

if (test1.Where(x => x.Pupil != null).Count(x => x.Pupil == null) > 0)
{
    var bp = "not hit"; // Without having to do this
}

Я предполагаю, что это некоторая проблема, связанная с отложенной загрузкой EF, но я попытался явно загрузить и включить их безрезультатно; единственное, что работает, - это вызов. ToList () для всего запроса, который будет оценивать прокси и позволять мне корректно исключать их, однако для этого он будет загружать данные, которые мне не нужны, а просто выбрасывать их. Есть ли способ обойти это?

Оригинальный метод решения проблемы:

public IEnumerable<Report> GetCurrentReportsForStaffByUsername(string username)
{
    var staffId =
        GetStaffIdFromUsername(username);

    var query = (
        from reports in this.DbContext.Reports.Include(x => x.Pupil).Where(x => x.Pupil != null)
       where reports.StaffId == staffId
          && reports.Pupil != null
      select reports)
            .Include(r => r.Pupil)
            .Where(r => r.Pupil != null);

    if (query.Any(q => q.Pupil == null))
    {
        var error = "how?!?!?!?!?!?!?!?"; // <-- Hits this
    }

    if (query.ToList().Any(q => q.Pupil == null))
    {
        var error = "really?";
    }

    return query;
}

Спасибо, что нашли время:)

Ответы [ 2 ]

0 голосов
/ 03 июля 2018

Обычно вы делаете что-то вроде этого: (основываясь на вашем примере)

public IEnumerable<Report> GetCurrentReportsForStaffByUsername(string username)
{
    var staffId =
        GetStaffIdFromUsername(username);

    var query = (
        from reports in this.DbContext.Reports
        join pupil in this.DbContext.Pupils on reports.PupilID equals pupil.PupilID
        where reports.StaffId == staffId
        select reports)

    return query;
}

Это станет примерно так в sql:

SELECT * FROM Report r
INNER JOIN Pupil p ON r.PupilID = p.PupilID

Что похоже на то, что вы хотите. Я бы также предложил инструмент, подобный Linqpad , для тестирования этих вещей, поскольку вы можете написать код на C #, и у него есть вкладка, чтобы показать, во что это превращается в SQL (хотя это не всегда 1-к-1 , но это дает вам представление)

Таким образом, вы можете попробовать разные подходы и примерно увидеть результаты.

0 голосов
/ 02 июля 2018

Не самый красивый код, но он делает то, что должен;

var test2 =
    DbContext.Report
        .Where(r => DbContext.Pupils.Any(p => p.PupilId == r.PupilId)).ToList();

или в linq to sql;

public IEnumerable<Report> GetCurrentReportsForStaffByUsername(string username)
{
    var staffId =
        GetStaffIdFromUsername(username);

    var query = (
        from reports in this.DbContext.Reports
       where reports.StaffId == staffId
          && this.DbContext.Pupils.Any(p => p.PupilID == reports.PupilID) // <- this
      select reports)

    return query;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...