как загрузить несколько связанных сущностей, но не со всеми его полями, с помощью include? - PullRequest
0 голосов
/ 02 июля 2019

У меня есть метод, который загружает много связанных сущностей, используя предложения include, но для создания запроса он слишком велик. Мне нужно загрузить много связанных объектов, но я хочу загрузить только те поля, которые важны для меня.

public RECEIPT_REMITS GetByIDWithIncludes(string UUID) 
{ 
   return Context.RECEIPT_REMITS.Where(h => h.UUID == UUID) .
   Include(r => r.DEPOSITE) 
  .Include(r => r.PROVIDER) 
  .Include(r => r.RECEIPT_KINDS) 
  .Include(r => r.RECEIPT_REMITS_DETAIL.Select(d => 
    d.RECEIPT_REMITS_SERIES)).FirstOrDefault(); 
} 

Теперь предложение загружает данные правильно, но только медленно, а также приносит поля, которые мне не нужны. Как я могу это сделать?

1 Ответ

1 голос
/ 03 июля 2019

Объекты представляют записи данных. Полные записи данных. Это делает их плохим выбором для использования в других целях, таких как модели для представлений. Вместо этого вам следует принять модели представления, а затем сопоставить объекты для просмотра моделей либо с помощью .Select(), либо с помощью Automapper с его методом .ProjectTo<T>(), который интегрируется с реализацией IQueryable EF. Даже если некоторые модели представлений оказываются идентичными модели EF, они служат отдельным целям. Сущность всегда должна представлять строку, с которой она связана, поэтому нельзя ожидать, что EF вернет частично заполненную сущность.

Например, если у меня есть таблица ReceiptRemit с 10 столбцами, которые мне нужны, и я также хочу включить связанные депозиты, но мне важны только идентификатор и сумма из таблицы депозитов:

Объекты:

[Table("RECEIPT_REMIT")]
public class ReceiptRemit
{
   [Key]
   public string UUID { get; set; }
   public string Field1 { get; set; }
   public string Field2 { get; set; }
   // etc. etc.
   public virtual ICollection<Demerit> Demerits { get; set; } = new List<Demerit>();
}
[Table("DEMERITE")]
public class Demerit
{
   [Key]
   [Column("DEMERITE_ID")]
   public int DemeritId { get; set; }
   public decimal Amount { get; set; }
   public string Field1 { get; set; }
   public string Field2 { get; set; }
   // etc. etc. to match the table, but stuff I don't care about...
}

Просмотр моделей:

[Serializable]
public class ReceiptRemitViewModel
{
   public string UUID { get; set; }
   public string Field1 { get; set; }
   public string Field2 { get ; set; }
   // etc. etc.
   public IEnumerable<DemeritSummaryViewModel> Demerits { get; set; } = new List<DemeritSummaryViewModel>();
}
[Serializable]
public class DemeritSummaryViewModel
{
   public int DemeritId { get; set;}
   public decimal Amount { get; set; }
}

Затем читать: (.Select())

public ReceiptRemitViewModel GetByID(string UUID) 
{ 
   return Context.ReceiptRemits.Where(h => h.UUID == UUID)
      .Select(x => new ReceiptRemitViewModel
      {
         UUID = x.UUID.
         Field1 = x.Field1,
         Field2 = x.Field2,
         Demerits = x.Demerits.Select(d => new DemeritSummaryViewModel
         {
            DemeritId = d.DemeritId,
            Amount = d.Amount
         }).ToList(),
       }.Single();
}

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

return Context.ReceiptRemits.Where(h => h.UUID == UUID)
  .ProjectTo<ReceiptRemitViewModel>()
  .Single();

В качестве альтернативы для таких вещей, как массовые операции, вы можете определить другое определение сущности для связанных данных и зарегистрировать эти альтернативные сущности в новом определении DbContext. Это должно быть отдельное объявление DbContext, потому что DbContext не может иметь 2 объекта, сопоставленных одной и той же таблице. Это хорошо работает в ситуациях, когда вам может понадобиться загрузить относительно большое количество записей для проверки и, возможно, обновления только поднабора связанных сущностей и полей.

...