【问题标题】:Code First load nested without recursion无递归嵌套的代码优先加载
【发布时间】:2013-05-21 15:22:03
【问题描述】:

我有一个可以包含许多部分的工作表。每个部分还可以包含许多部分。我想以尽可能少的往返数据库的方式加载工作表、其部分和所有子部分。实际上,我认为这通常是 1-2 级深度,但可能会达到 16 级。代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;

public class Sheet {
    public long Id { get; set; }
    // more fields
    public virtual IList<Section> Sections { get; set; }
}

public class Section {
    public long Id { get; set; }

    public long SheetId { get; set; }
    [ForeignKey("SheetId")]
    public virtual Sheet Sheet { get; set; }

    public long? ParentId { get; set; }
    [ForeignKey("ParentId")]
    public virtual Section Parent { get; set; }

    public virtual IList<Section> Sections { get; set; }
    // more fields
}

public class MyDbContext : DbContext {
    public DbSet<Sheet> Sheets { get; set; }
    public DbSet<Section> Sections { get; set; }
    public Sheet GetSheetConfiguration(long id) {
        Configuration.LazyLoadingEnabled = false;
        Sheet rtn;
        rtn = Sheets.Find(id);
        (Sections.Where(sect => sect.SheetId == id)).ToList();
        return rtn;
    }
}

这将创建所需的表结构: 工作表:ID (pk), ... 部分:Id (pk)、SheetId(非空)、ParentId(空)

GetSheetConfiguration 方法加载与该工作表相关的所有部分,并让 EF 对其进行排序。它使关系正确,除了所有部分也在 Sheet.Sections 中。 (我想为每个部分设置 SheetId 以避免递归查询。)如何告诉 EF 在工作表级别仅使用 ParentId = null 的部分? - 列表项

【问题讨论】:

  • 您为GetSheetConfiguration 发布的代码是否正确?我不明白(Sections.Where ... )这一行@
  • 目的是加载该工作表的所有部分,然后让 EF 对其进行排序。正如@Slauma 建议的那样,说Sections.Where(sect =&gt; sect.SheetId == id).Load(); 会更清楚

标签: c# .net ef-code-first entity-framework-5 code-first


【解决方案1】:

您无法避免 Sheet.Sections 集合被 all 部分填充,因为这就是 Sheet.SectionsSection.Sheet 之间的关系所描述的:它应该包含所有部分,不仅是ParentId == null 的“根部分”。实体框架根据关系修复填充此集合,您无法禁用或配置此行为。

解决该问题的一个选项是引入一个额外的集合属性,该属性从Sheet.Sections 导航属性中读取过滤后的数据,并且未映射到数据库以检索根部分的列表,如下所示:

public class Sheet {
    public long Id { get; set; }
    // more fields
    public virtual IList<Section> Sections { get; set; }

    public IEnumerable<Section> RootSections
    {
        get { return Sections.Where(sect => sect.ParentId == null); }
    }
}

小旁注:而不是...

(Sections.Where(sect => sect.SheetId == id)).ToList();

...你可以使用:

Sections.Where(sect => sect.SheetId == id).Load();

Load 是一个 void 方法,它只是将请求的实体加载到上下文中。它节省了创建不必要的List 集合的开销。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多