使用entity framework加载所有子实体

我有这样的数据模型

数据模型

我想将对帐中的所有相关实体加载到Reconciliation对象中。

目前,我可以找到将所有相关的entites加载到单个Recon的唯一方法是多个列表。 但我想在Reconciliation对象中加载每个相关实体。 如果可能的话,优雅的方式。

 Reconciliation recon = db.Reconciliations .Where(r => r.ReconNum == 382485).First(); List reconDetails = recon.ReconciliationDetails.ToList(); List jrnlDetails = reconDetails.Select(r => r.JrnlEntryDetail).ToList(); List jrnl = jrnlDetails.Select(j => j.JrnlEntry).ToList(); List invoices = jrnl.SelectMany(j => j.ARInvoices).ToList(); List invoicesDetail = invoices .SelectMany(i => i.ARInvoiceDetails).ToList(); List credmemos = jrnl.SelectMany(j => j.ARCredMemoes).ToList(); List credmemosDetail = credmemos .SelectMany(c => c.ARCredMemoDetails).ToList(); List incomingPays = jrnl.SelectMany(j => j.IncomingPays).ToList(); List incomingPaysDetail = incomingPays .SelectMany(i => i.IncomingPayDetails).ToList(); // ... and so on for outgoing pays, AP Invoices AP Cred Memo ...etc 

我也尝试使用IncludeSelect加载它,但是我得到了这个例外:

Include路径表达式必须引用在类型上定义的导航属性。 使用虚线路径作为参考导航属性,使用Select运算符作为集合导航属性。

而且我不知道如何使用IncludeSelect加载JrnlEntry的每个孩子

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

编辑

管理也是这样做但它不是很漂亮:

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

有两种方法可以在Entity Framework中执行Eager Loading

  • ObjectQuery.Include方法
  • 使用DbEntityEntry.Collection方法或DbEntityEntry.Reference方法及其各自的Load方法显式加载

还有一种方法可以针对数据库编写Raw SQL查询 :

  • DbSet.SqlQuery方法处理实体
  • Database.SqlQuery方法处理任意类型
  • Database.ExecuteSqlCommand用于任意DDL / DML的方法

对于这种情况,当您尝试加载几乎整个数据库时,最好对其执行专用存储过程。

最初尝试使用.Include(r => r.ReconciliationDetails) 。 然后逐个添加.Select()语句。 exception重新出现在什么时候? .SelectMany()调用看起来有点可疑!

第二个问题可能有助于识别问题…运行包含所有ToList()调用的代码后,您的recon实体是否完成? 即它的所有导航属性是否已填充? 这应该是这种情况,因为entity framework的自动“修复”行为。

使用EF,有时使用多个调用而不是链接的Include()调用来加载复杂的对象图更有效。 检查生成的SQL,看看哪种情况最有效。

不确定是否为时已晚,但您可以从构建代码中受益,例如

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