Выберите только определенные поля из необязательного свойства навигации - PullRequest
1 голос
/ 10 мая 2019

У меня есть две сущности - User и Plan

class Plan
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string FieldA { get; set; }
    public string FieldB { get; set; }
    ...
}

class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int PlanId { get; set; }
    public Plan Plan { get; set; }
}

Я хочу выбрать конкретного пользователя и заполнить его Plan свойством, но только с конкретными полями (Id и Name).Я знаю, что это должно быть просто, мне просто нужно написать

db.Users
  .Select(u => new User()
  {
      Id = u.Id,
      Name = u.Name,
      PlanId = u.PlanId,
      Plan = new Plan()
      {
          Id = u.Plan.Id,
          Name = u.Plan.Name
      }
  })
  .SingleOrDefault(u => u.Id == 1);

Хитрость в том, что Plan является необязательным (не в том смысле, что PlanId может быть нулевым, но в том смысле, что PlanId можетуказывает на объект Plan, который не существует).

Когда Plan существует, все работает, как и ожидалось, но когда этого не происходит, свойство Plan все еще заполняется, с Idно с нулевым Name

Пример:

{
    "Id": 1,
    "Name": "some name..",
    "PlanId": 9, // There is no Plan object with Id = 9
    "Plan": {
        "Id": 9,
        "Name": null
    }
}

Я ожидаю, что Plan будет нулевым.Как мне этого добиться?

Спасибо

Ответы [ 2 ]

0 голосов
/ 10 мая 2019

Используйте GroupJoin вот так

var userPlanPair = db.Users
  .GroupJoin(db.Plans, u => u.PlanId, p => p.Id, (user, plans) => new { user, plans })
  .SelectMany(pair => pair.plans.DefaultIfEmpty(), (pair, plan) => new { pair.user, plan = plan != null ? new Plan() { Id = plan.Id, Name = plan.Name } : null })
  .SingleOrDefault(pair => pair.user.Id == 1);

Комбинация GroupJoin, SelectMany и DefaultIfEmpty преобразуется в левое соединение в форме SQL.

Внутри resultSelectorиз SelectMany вы запрашиваете конкретные поля, которые вам нужны из Plan.

Чтобы получить окончательный результат - объект User со свойством Plan, вы просто выбираете пользователя и план изпара.

var user = userPlanPair.user;
user.Plan = userPlanPair.plan;
0 голосов
/ 10 мая 2019

Почему бы просто не поставить условие для заполнения поля Plan?

db.Users
.Select(u => new User()
{
    Id = u.Id,
    Name = u.Name,
    PlanId = u.PlanId,
    Plan = u.Plan.Name == null ? null : new Plan()
    {
        Id = u.Plan.Id,
        Name = u.Plan.Name
    }
})
.SingleOrDefault(u => u.Id == 1);

После обсуждения в комментариях другой подход будет:

db.Users
.Select(u => new User()
{
    Id = u.Id,
    Name = u.Name,
    PlanId = u.PlanId,
    Plan = db.Plans.Find(u.PlanId)
})
.SingleOrDefault(u => u.Id == 1);

Find должен вернуть null, если Plan с u.PlanId не найден (в текущем контексте или хранилище)

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