实体框架核心-递归父/子链接

时间:2018-10-08 22:41:04

标签: entity-framework-core

我有一个“帐户”表,该表包含一个字符串外键(“ parent_guid”)到其“父母”帐户(如果存在)。我想创建一个知道其父代及其所有子代的实体。

这是我的实体:

[Table(name:"accounts")]
public class Account
{
    [Key]
    public string Guid { get; set; }
    public string Name { get; set; }

    [Column("guid")]
    public string accountGuid { get; set; }

    [Column(name: "parent_guid")]
    public string parentGuid { get; set; }

    [ForeignKey("parentGuid")]
    public Account Parent { get; set; }

    [InverseProperty("Parent")]
    public ICollection<Account> Children { get; set; }
}

这是我的dbContext:

public DbSet<Split> Splits { get; set; }
public DbSet<Account> Accounts { get; set; }

public ReportContext(DbContextOptions<ReportContext> options)
    : base(options)
    { }

我的查询是通过'splits'上下文作为源表,但最终返回了Accounts。也许有更好的方法?

当我通过Guid查询一个帐户时,得到一个结果,但是即使'parentGuid'包含正确的值,'Parent'和'Children'始终为空,并且我已经确认应该有子记录。

有人知道如何通过注释或流畅的API来完成这项工作吗?

1 个答案:

答案 0 :(得分:1)

是的,EFCore需要明确包含关系实体。

var accounts = await dbContext.Accounts.include(account => account.Parent)
                                       .include(account => account.Children)
                                       .ToListAsync();

编辑

根据对问题的编辑,这是急于加载关系实体的一种方法,但是在不了解关系和索引的情况下,我无法说出此查询的效率。

public IQueryable<Split> 
  FindAllByAccountGuidsPostedBefore(IEnumerable<string> accounts, 
                                                       DateTime endDate) {
  using (reportContext) { 
     return reportContext.Splits.Include(s => s.Account)
                                .ThenInclude(a => a.Parent)
                                .ThenInclude(a => a.Children)
                                .Where(s => accounts.Contains(s.Account.Guid) 
                                 && s.Transaction.postDate < endDate); 
     } 
} 

获取该信息的一种方法是运行此查询时查看控制台以查找生成的SQL语句,或者询问关系数据库中经验更丰富的人:)