【问题标题】:Eagerly/explicitly load "child" entities with only navigation property to "parent"急切/明确地将只有导航属性的“子”实体加载到“父”
【发布时间】:2019-04-09 06:29:02
【问题描述】:

我有一个 EF Core 2.1 Code First 模型,在两个类之间具有“父子”类型关系:

class Parent
{
    public int Id {get; set;}
    public string Name {get; set;}
}

class Child
{
    public int Id {get; set;}
    public string Description { get; set; }
    public Parent Parent { get; set; }
}

我想加载某个父级,并确保它的所有子级实体也都已加载。但是,Child 没有导航属性,我无法修改类,因此无法添加。

dbContext.Parents
    .Include(p => p.???)
    .Find(1);

我想我可以进行第二次查询,在其中反向查找所有内容:

dbContext.Children.Where(c => c.Parent.Id == loadedParent.Id)

但这似乎不是很有效,尤其是当您加载多个父母并执行以下可怕的事情时:

var parentIds = loadedParents.Select(p => p.Id);
var children = dbContext.Children.Where(c => parentIds.Contains(c.Parent.Id));

当您只有“子到父”导航属性时,是否有办法确保实体已加载?

【问题讨论】:

    标签: entity-framework linq ef-code-first ef-core-2.1


    【解决方案1】:

    确保其所有子实体也已加载

    所以加载Child 实体:

    var children = dbContext.Children.Include(c => c.Parent)
        .Where(c => c.Parent.Id == 1).ToList();
    

    如果您想获得多个父母,请使用比 c.Parent.Id == 1 更广泛的选择标准。

    如有必要,您可以通过访问Local 集合列出加载的父级:

    va parents = dbContext.Parents.Local;
    

    【讨论】:

    • 这真的是最有效的方法吗?似乎数据库查询很快就会变得更加复杂。
    • 就效率而言,生成的 SQL 几乎与具有parent.Children 的查询相同。至于复杂性,有一个谓词Where(c => c.Parent ...) 而不是Where(p => p ...)。我看不出这种复杂性如何成倍增长。唯一的区别(与包括孩子相比)是你不会得到没有孩子的父母。如果这是一个问题,您应该使用 GroupJoin(外连接的 LINQ 等效项)。
    • 使用多个父 ID 执行此操作的最有效方法是什么?是 Where(c => parentIds.Contains(c.Id) 还是有生成更好 SQL 的方法?
    • ContainsparentIds 不太长(几千个)时很好。如果是,你可以试试this
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多