EFCore: запрос нескольких связанных данных - PullRequest
0 голосов
/ 17 декабря 2018

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

У меня есть список проектов, для каждого проекта может быть установлено несколько базовых показателей (или их нет), каждая базовая линия содержит несколько этапов.Спроектированный список проектов должен содержать свойство, которое содержит определенный этап в самой последней установленной базовой линии.

Моя модель находится в SQL через EFCore:

public class Project
{
    public int ProjectID { get; set; }
    public string Name { get; set; }
    public ICollection<Baseline> Baselines { get; set; }
}

public class Baseline
{
    public int BaselineID { get; set; }
    public int ProjectID { get; set; }
    public Project Project { get; set; }
    public string Name { get; set; }
    public DateTime DateSet {get; set;}
    public string Description { get; set; }
    public ICollection<BaselineDate> BaselineDates { get; set; }
}

public class BaselineDate
{
    public int BaselineDateID { get; set; }
    public int BaselineID { get; set; }
    public Baseline Baseline { get; set; }
    public int MilestoneTypeID { get; set; }
    public MilestoneType MilestoneType { get; set; }
    public DateTime Date { get; set; }
    public string Comment { get; set; }
}

В моем контроллере я определяюпроектируемый класс:

public class ProjectInfo
{
    public int ProjectID { get; set; }
    public string ProjectName { get; set; }
    public DateTime? ProjectStart { get; set; }
}

public IList<ProjectInfo> ProjectInfoList { get; set; }

А затем в функции я пытаюсь использовать efcore для запроса моделей:

ProjectInfoList = await _context.Project
     .Where(project => project.Branch == Branch)
     .Select(project => new ProjectSummary
         {
             ProjectID = project.ProjectID,
             ProjectName = project.Name,
             ProjectStart = project.Baselines
                 .DefaultIfEmpty(new Baseline { BaselineDates = new List<BaselineDate>() })
                 .OrderByDescening(b => b.DateSet)
                 .FirstOrDefault()
                 .BaselineDates
                 .Where(d => d.Comment == "Project Start")
                 .FirstOrDefault()
                 .Date
          }
       .AsNoTracking()
       .ToListAsync();

Это работает нормально, если для каждого проекта существует базовая линия,Однако, когда проект существует без базовой линии, генерируется нулевое исключение.

ArgumentNullException: значение не может быть нулевым.Имя параметра: source System.Linq.Enumerable.Where (источник IEnumerable, предикат Func)

Я пытаюсь добавить в .DefaultIfEmpty (new Baseline ()), но выдает больше исключений.

1 Ответ

0 голосов
/ 17 декабря 2018

Имейте в виду, что Entity Framework переводит все выражение LINQ в SQL (точнее, пытается сделать это).Поскольку в SQL нет понятия нулевых ссылок, вы можете смело использовать выражение, которое в коде C # (или: LINQ-to-objects) сгенерировало бы исключение нулевой ссылки.

Но, кроме этого, нарушающая подпрограммазапрос может быть переписан так, чтобы даже в LINQ-to-objects он не выдавал исключение, если свойства коллекции не равны NULL:

ProjectInfoList = await _context.Project
     .Where(project => project.Branch == Branch)
     .Select(project => new ProjectSummary
         {
             ProjectID = project.ProjectID,
             ProjectName = project.Name,
             ProjectStart = (from bl in project.Baselines
                from bd in bl.BaselineDates
                where bd.Comment == "Project Start"
                orderby bl.DateSet descending, bd.Date descending
                select (DateTime?)bd.Date).FirstOrDefault()
          }
       .AsNoTracking()
       .ToListAsync();

Я делаю это в синтаксисе запроса для лучшей читаемости.Конструкция from ... from имеет синтаксис SelectMany в методе.Синтаксис SelectMany, когда требуются данные как от родителей, так и от детей (bl.DateSet, bd.Date), довольно неудобен.

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