EF核心-parent.InverseParent对于某些行返回null

时间:2019-05-06 10:21:34

标签: entity-framework .net-core entity-framework-core

我有一个类别表,并且有一个父类别,我尝试遍历所有类别并使用“反向父项”获得父项类别,但是其中一些返回原因是未知原因而没有反向父项。

Categories.cs

 public partial class Categories
{
    public Categories()
    {
        InverseParent = new HashSet<Categories>();   
    }

    public int Id { get; set; }
    public int? ParentId { get; set; }
    public DateTime CreateDate { get; set; }
    public bool? Status { get; set; }

    public virtual Categories Parent { get; set; }

    public virtual ICollection<Categories> InverseParent { get; set; }

}

这是我尝试迭代它们以创建选择列表项的方法:

  var parentCategories = await _context.Categories.
                                                      Include(x => x.Parent).
                                                      Where(x => x.Status == true).
                                                      Where(x => x.Parent != null).
                                                      Select(x => x.Parent).
                                                      Distinct().
                                                      ToListAsync();

                foreach (var parent in parentCategories)
                {
                    SelectListGroup group = new SelectListGroup() { Name = parent.Id.ToString() };
                    foreach (var category in parent.InverseParent)
                    {
                        categories.Add(new SelectListItem { Text = category.Id.ToString(), Value = category.Id.ToString(), Group = group });
                    }
                }

所以问题是我的某些父类别返回了他们所有的子类别,有些却没有,我也不为什么。

2 个答案:

答案 0 :(得分:2)

该代码存在多个问题,在文档的Loading Related Data部分中都有一些解释。

首先,您没有要求EF Core包含InverseParent,所以更合乎逻辑的是期望它总是 null

您得到的是以下Eager Loading行为的结果:

  

提示

     

Entity Framework Core将自动将导航属性修复为先前加载到上下文实例中的任何其他实体。因此,即使您未明确包含导航属性的数据,如果先前已加载了部分或全部相关实体,该属性仍可能被填充。

第二,由于查询正在更改其初始形状(SelectDisctinct),因此它属于Ignored Includes类别。

话虽如此,您应该以其他方式构建查询-直接从父类别开始并包括InverseParent

var parentCategories = await _context.Categories
    .Include(x => x.InverseParent)
    .Where(x => x.InverseParent.Any(c => c.Status == true)) // to match your query filter
    .ToListAsync();

答案 1 :(得分:0)

虽然您包括Include(x => x.Parent),但似乎对InverseParent却没有这样做。这可能会完全按照您的描述方式影响您的结果。包括它会解决吗?

parentCategories = await _context.Categories.
                                                      Include(x => x.Parent).
                                                      Include(x => x.InverseParent).
                                                      Where(x => x.Status == true).
                                                      Where(x => x.Parent != null).
                                                      Select(x => x.Parent).
                                                      Distinct().
                                                      ToListAsync();

                foreach (var parent in parentCategories)
                {
                    SelectListGroup group = new SelectListGroup() { Name = parent.Id.ToString() };
                    foreach (var category in parent.InverseParent)
                    {
                        categories.Add(new SelectListItem { Text = category.Id.ToString(), Value = category.Id.ToString(), Group = group });
                    }
                }

UPD:由于无论如何选择x => x.Parent,可能有必要改为使用ThenInclude()方法。