Arno 2501
Arno 2501

Reputation: 9417

Loading all the children entities with entity framework

I have a data model like this

Data Model

I would like to load all the related entities from a Reconciliation into a Reconciliation object.

For now the only way I could find to load all the related entites to a single Recon is in multiple Lists. But I want to load every related entities in a Reconciliation object. If possible in an elegant way.

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

I have also tried to load it with Include and Select but I get this exception :

The Include path expression must refer to a navigation property defined on the type. Use dotted paths for reference navigation properties and the Select operator for collection navigation properties.

And I don't get how I could load every childs of JrnlEntry using Include and 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

Managed to do it this way too but it's not very beautiful :

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))

Upvotes: 29

Views: 76648

Answers (3)

JQII
JQII

Reputation: 175

Not sure if it's to late but could you benefit from structuring your code such as

var acctName = "someName";

var detailList =  _repository.Include(e => e.JrnlEntryDetail).Filter(c => c.JrnlEntryDetail.Any(e => e.AcctName == acctName)).Get().ToList();

Upvotes: 1

Ryszard Dżegan
Ryszard Dżegan

Reputation: 25464

There are two ways to perform Eager Loading in Entity Framework:

There are also manners to write Raw SQL Queries against database:

For the case, when you're attempting to load nearly entire database, it would be good idea to execute dedicated store procedure against it.

Upvotes: 28

Olly
Olly

Reputation: 6026

Try with just .Include(r => r.ReconciliationDetails) initially. Then add the .Select() statements one-by-one. At what point does the exception reappear? The .SelectMany() call looks a bit suspicious to me!

A second question that might help identify the problem... After you run the code that contains all the ToList() calls, is your recon entity complete? i.e. are all its navigation properties populated? This should be the case because of the automatic 'fixup' behavior of Entity Framework.

With EF, sometimes it is more efficient to load a complex object graph with several calls rather than chained Include() calls. Check the generated SQL and see what is most efficient in your case.

Upvotes: 8

Related Questions