使用实体框架加载所有子实体

时间:2013-11-08 13:40:34

标签: c# entity-framework-5

我有这样的数据模型

Data Model

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

现在我能找到将所有相关的entites加载到单个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

我还尝试使用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))

3 个答案:

答案 0 :(得分:26)

在实体框架中有两种方法可以执行 Eager Loading

还有一种方法是对数据库编写Raw SQL Queries

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

答案 1 :(得分:7)

最初只试用.Include(r => r.ReconciliationDetails)。然后逐个添加.Select()语句。异常再次出现在什么时候? .SelectMany()电话看起来有些可疑!

可能有助于识别问题的第二个问题...运行包含所有ToList()次调用的代码后,您的recon实体是否已完成?即是否填充了所有导航属性?由于Entity Framework的自动“修复”行为, 应该。

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

答案 2 :(得分:0)

不确定是否会迟到,但您可以从构建代码中受益,例如

var acctName = "someName";

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