Загрузка всех дочерних объектов с инфраструктурой сущностей
У меня есть модель данных, подобная этой
![Data Model]()
Я хотел бы загрузить все связанные объекты из объекта "Согласование в объект примирения".
Теперь единственный способ найти все связанные с ним права на один Recon - это несколько списков. Но я хочу загрузить все связанные объекты в объекте Reconciliation
. Если это возможно элегантным способом.
Reconciliation recon = db.Reconciliations
.Where(r => r.ReconNum == 382485).First();
List<ReconciliationDetail> reconDetails = recon.ReconciliationDetails.ToList();
List<JrnlEntryDetail> jrnlDetails = reconDetails.Select(r => r.JrnlEntryDetail).ToList();
List<JrnlEntry> jrnl = jrnlDetails.Select(j => j.JrnlEntry).ToList();
List<ARInvoice> invoices = jrnl.SelectMany(j => j.ARInvoices).ToList();
List<ARInvoiceDetail> invoicesDetail = invoices
.SelectMany(i => i.ARInvoiceDetails).ToList();
List<ARCredMemo> credmemos = jrnl.SelectMany(j => j.ARCredMemoes).ToList();
List<ARCredMemoDetail> credmemosDetail = credmemos
.SelectMany(c => c.ARCredMemoDetails).ToList();
List<IncomingPay> incomingPays = jrnl.SelectMany(j => j.IncomingPays).ToList();
List<IncomingPayDetail> incomingPaysDetail = incomingPays
.SelectMany(i => i.IncomingPayDetails).ToList();
// ... and so on for outgoing pays, AP Invoices AP Cred Memo ...etc
Я также попытался загрузить его с помощью Include
и Select
, но я получаю это исключение:
В выражении Include path должно быть указано свойство навигации, определенное в типе. Используйте пунктирные пути для ссылочных навигационных свойств и оператор Select для свойств навигации для коллекции.
И я не понимаю, как я мог загружать все дочерние элементы JrnlEntry с помощью Include
и Select
Reconciliation recon = db.Reconciliations
.Where(r => r.ReconNum == 382485)
.Include(r => r.ReconciliationDetails
.Select(d => d.JrnlEntryDetail)
.Select(jd => jd.JrnlEntry)
.SelectMany(j => j.ARInvoices).SelectMany(i => i.ARInvoiceDetails))
Edit
Удалось это сделать тоже, но это не очень красиво:
Reconciliation recon = db.Reconciliations
.Where(r => r.ReconNum == 382485)
.Include(r => r.ReconciliationDetails.Select(rd => rd.JrnlEntryDetail)
.Select(jd => jd.JrnlEntry).Select(j => j.ARInvoices.Select(i => i.ARInvoiceDetails)))
.Include(r => r.ReconciliationDetails.Select(rd => rd.JrnlEntryDetail)
.Select(jd => jd.JrnlEntry).Select(j => j.ARCredMemoes.Select(c => c.ARCredMemoDetails)))
.Include(r => r.ReconciliationDetails.Select(rd => rd.JrnlEntryDetail)
.Select(jd => jd.JrnlEntry).Select(j => j.IncomingPays.Select(i => i.IncomingPayDetails)))
.Include(r => r.ReconciliationDetails.Select(rd => rd.JrnlEntryDetail)
.Select(jd => jd.JrnlEntry).Select(j => j.OutgoingPays.Select(o => o.OutgoingPayDetails)))
.Include(r => r.ReconciliationDetails.Select(rd => rd.JrnlEntryDetail)
.Select(jd => jd.JrnlEntry).Select(j => j.APInvoices.Select(o => o.APInvoiceDetails)))
.Include(r => r.ReconciliationDetails.Select(rd => rd.JrnlEntryDetail)
.Select(jd => jd.JrnlEntry).Select(j => j.APCredMemoes.Select(o => o.APCredMemoDetails)))
.Include(r => r.ReconciliationDetails.Select(rd => rd.JrnlEntryDetail)
.Select(jd => jd.JrnlEntry).Select(j => j.JrnlEntryDetails))
Ответы
Ответ 1
Есть два способа выполнить Ожидание загрузки в Entity Framework:
Есть также манеры писать Необработанные SQL-запросы для базы данных:
В случае, когда вы пытаетесь загрузить почти всю базу данных, было бы неплохо выполнить над ним специальную процедуру хранения.
Ответ 2
Сначала попробуйте только .Include(r => r.ReconciliationDetails)
. Затем добавьте операторы .Select()
один за другим. В какой момент снова появляется исключение? Вызов .SelectMany()
выглядит немного подозрительным для меня!
Второй вопрос, который может помочь выявить проблему... После запуска кода, который содержит все вызовы ToList()
, завершен ли ваш объект recon
? т.е. все его навигационные свойства заполнены? Это должно происходить из-за автоматического "исправления" поведения Entity Framework.
С EF, иногда более эффективно загружать граф сложного объекта несколькими вызовами, а не цепочками Include()
вызовов. Проверьте сгенерированный SQL и посмотрите, что наиболее эффективно в вашем случае.
Ответ 3
Не уверен, что это возможно, но вы могли бы использовать структурирование своего кода, например
var acctName = "someName";
var detailList = _repository.Include(e => e.JrnlEntryDetail).Filter(c => c.JrnlEntryDetail.Any(e => e.AcctName == acctName)).Get().ToList();