ASP.Net Core和EF Core:递归包含子项并映射到视图模型

时间:2019-06-12 14:10:27

标签: entity-framework-core mapping

我有一些代表分层组织的类。为简化起见,有一个企业类(企业),其中包含一些属性和 Unity (组织项)的集合。

第二个 Unite 类具有一些属性,并且可能像企业一样具有 Unite 的集合。

级别数(与儿童,儿童和儿童等结合在一起)是未知的。

最后,我有一个ViewModel类来公开此数据的部分视图。

模型&& ViewModel

[Table("Entreprise", Schema = "Structure")]
public partial class Entreprise
{

    public Entreprise()
    {
        Unites = new HashSet<Structure.Unite>();
    }

    [Key]
    public int Id { get; set; }

    [StringLength(128)]
    public string Libelle { get; set; }

    public virtual ICollection<Structure.Unite> Unites { get; set; }

}

[Table("Unite", Schema = "Structure")]
public partial class Unite
{

    #region Constructeur

    public Unite()
    {
        UnitesChild = new HashSet<Structure.Unite>();
    }

    [Key]
    public int Id { get; set; }

    [ForeignKey("Entreprise")]
    public int? IdEntreprise { get; set; }

    [ForeignKey("UniteParent")]
    public int? IdUniteParent { get; set; }

    [StringLength(128)]
    public string Libelle { get; set; }

    public virtual Structure.Entreprise Entreprise { get; set; }

    public virtual Structure.Unite UniteParent { get; set; }

    public virtual ICollection<Structure.Unite> UnitesChild { get; set; }

}


public class ListWithUnites
{
    public int Id { get; set; }
    public string Libelle { get; set; }
    public List<UniteCL> Unites { get; set; }

    public class UniteCL
    {
        public int Id { get; set; }
        public string Libelle { get; set; }
        public List<UniteCL> Unites { get; set; }
    }
}

我想做的是:

1-加载企业->子级合并,还加载Unite->子级合并,直到最后一级

2-将查询结果映射到视图模型

如果您对此有何建议,在此先非常感谢。

2 个答案:

答案 0 :(得分:0)

我做了以下类似的事情。但是我仍然对获取数据的sql查询数量感到恼火。

是否没有生成联接查询的解决方案,或者有效率更高的解决方案?

public List<ListWithUnites> ListWithUnites()
{
    // Get entreprises and first level
    List<ListWithUnites> tmpResult = _dbContext.Structure_Entreprises
        .Include(ent => ent.Unites)
        .Select(ent => new ListWithUnites
        {
            Id = ent.Id,
            Libelle = ent.Libelle,
            Unites = ent.Unites.Select(uni => new ListWithUnites.UniteCL
            {
                Id = uni.Id,
                Libelle = uni.Libelle
            }).ToList()
        }).ToList();

    // Load unites
    foreach (ListWithUnites e in tmpResult)
    {
        for (var i = 0; i < e.Unites.Count; i++)
        {
            ListWithUnites.UniteCL tmpUnite = e.Unites[i];
            LoadUniteCL(ref tmpUnite);
            e.Unites[i] = tmpUnite;
        }
    }

    return tmpResult;
}

private void LoadUniteCL(ref ListWithUnites.UniteCL unite)
{
    // Get Id from ref unite
    int idUnite = unite.Id;

    // Load child unites from ref
    unite.Unites = _dbContext.Structure_Unites
        .Where(uni => uni.IdUniteParent == idUnite)
        .Select(uni => new ListWithUnites.UniteCL
        {
            Id = uni.Id,
            Libelle = uni.Libelle,
        }).ToList();

    // Load recursively
    for (var i = 0; i < unite.Unites.Count; i++)
    {
        ListWithUnites.UniteCL tmpUnite = unite.Unites[i];
        LoadUniteCL(ref tmpUnite);
        unite.Unites[i] = tmpUnite;
    }
} 

答案 1 :(得分:0)

我认为我找到了一个很好的答案:

  1. 因为我想从我的api中获取json对象,所以不需要显式的视图模型
  2. 由于类型为Unite的实体链接到Entreprise及其自身,因此我可以告诉EFCore在我的查询中仅包含 Entreprise.UnitesChild ,这将产生魔力并设置Unites之间的级联关系。
  3. 我可以在自己的选择中使用递归函数

这是最终代码:

=QUERY('Table 1'!A2:G500, "Select F Where G <> '#N/A'")