Объекты представляют записи данных. Полные записи данных. Это делает их плохим выбором для использования в других целях, таких как модели для представлений. Вместо этого вам следует принять модели представления, а затем сопоставить объекты для просмотра моделей либо с помощью .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 объекта, сопоставленных одной и той же таблице. Это хорошо работает в ситуациях, когда вам может понадобиться загрузить относительно большое количество записей для проверки и, возможно, обновления только поднабора связанных сущностей и полей.