【问题标题】:EF code-first: How to load related data (parent-child-grandchild)?EF 代码优先:如何加载相关数据(父子孙子)?
【发布时间】:2011-11-22 10:07:17
【问题描述】:

我有这个实体:

public class DynamicPage {

    public int PageId { get; set; }

    public int Order { get; set; }

    public string MenuText { get; set; }

    public string MenuHover { get; set; }

    public int? ParentId { get; set; }

    public virtual DynamicPage Parent { get; set; }

    public virtual ICollection<DynamicPage> Children { get; set; }
}

该实体可能有 3 个级别:父级 -> 子级 -> 孙子级。我如何加载父级(级别 1)和所有关联的子级(级别 2)以及每个子级的关联孙子级(级别 3)(如果有)?感谢帮助。

【问题讨论】:

    标签: entity-framework ef-code-first entity-framework-5 entity-framework-4.1 entity-framework-6


    【解决方案1】:

    如果您想让自己的生活更轻松,请遵循 EF Code First 约定,将您的表 ID 命名为 Id(或者,表名称 + Id,例如 DyanmicPageId)。

    这应该会给你留下这样的东西:

    public class DynamicPage
    {
        public int Id { get; set; }
        public int Order { get; set; }
        public string MenuText { get; set; }
        public string MenuHover { get; set; }
        public int? ParentId { get; set; }
    
        public virtual DynamicPage Parent { get; set; }
        public virtual ICollection<DynamicPage> Children { get; set; }
    }
    

    那么你需要在你的DbContext类的OnModelCreating方法中明确地建立父母和孩子之间的关系。

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<DynamicPage>()
            .HasMany(page => page.Children)
            .WithRequired(child => child.Parent)
            .HasForeignKey(child => child.ParentId);
    }
    

    然后您可以根据需要选择子或孙:

    var parent = dbContext.DynamicPages.Where(page => page.ParentId == null);
    var children = parent.Children;
    var grandchildren = parent.SelectMany(page => page.Children);
    var allRelatedPages = parent.Union(children).Union(grandchildren);
    

    【讨论】:

    • 你在说什么?请再次阅读问题:如何加载父级(级别 1)和所有关联的子级(级别 2)以及每个子级、关联的孙子级(级别 3)(如果有)? 我知道如何映射实体,并知道如何在 2 级关系 Parent-Child 中加载它们。但我无法加载 3 级关联。就这个!
    • “加载”是什么意思?你的意思是选择吗?
    • 从数据库加载,从数据库中获取,选择。像这样:entity.DynamicPages.Where(d =&gt; d.ParentId == null).Include(d =&gt; d.Children).ToList(); 我知道这个,但我想加载 d.Children.Children 我不能):
    • 更新了我的答案。希望这就是您想要的。
    • 现在我看到了 Slauma 的回答,我明白了你在寻找什么。而且我也学到了一些东西,所以没问题。
    【解决方案2】:

    EF 4.1 特性和语法:

    var entity = context.Parents
        .Include(p => p.Children.Select(c => c.GrandChildren))
        .FirstOrDefault(p => p.Id == 1); // or whatever condition
    

    【讨论】:

    • 没有名为GrandChildren 的属性。你的意思是这个代码:Include(p =&gt; p.Children.Select(c =&gt; c.Children))
    • @Javad_Amiry:是的。实际上,我写的GrandChildren 可以是任何导航属性——集合或引用。模式Include(x =&gt; x.SomeCollection.Select(c =&gt; c.SomeNavigationProperty)) 只会导致Include 用于下一个级别。您可以无限重复该广告:Select 用于集合,简单的虚线路径用于引用。
    • 好的,这工作正常 :D 非常感谢。在继续,我需要在取孩子时订购孩子(以及孙子)。我将编辑您的答案并放入我的第一个代码以及您的指导创建的最终代码来解释我的问题。请帮我完成解决方案。特别感谢关注问题。问候
    • @Javad_Amiry:最好针对您的排序问题提出一个新问题,因为 1)与我的回答中的编辑相比,更多人会看到一个新问题,以及 2)我现在离线 :)
    • @ChrisMoschini:不,它没有改变。 Include 的表达式重载仍然存在。确保在源文件中包含 using System.Data.Entity;
    猜你喜欢
    • 2012-05-09
    • 2013-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多