Entity Framework 条件无效的 .Include()

Entity Framework .Include() with condition not working

场景

如果我拆分 Entity Framework linq 查询以首先评估 IQueryable,然后再尝试包含一些属性,则 AccessGroupAccessPointsAccessGroupAccessPoints.AccessPoint 的值将不会包含在最后。

    public Task<List<AccessGroup>> GetAll(bool includeRelations)
    {
        var q = context.Set<AccessGroup>().AsNoTracking();

        if (includeRelations)
        {
            q.Include(a => a.AccessGroupAccessPoints)
                .ThenInclude(a => a.AccessPoint);
        }
        
        return q.ToListAsync();
    }

我也尝试删除 .ThenInclude(),使用字符串作为 .Include() 的参数,移动 .AsNoTracking() 来解决...这些选项都不起作用。

    public Task<List<AccessGroup>> GetAll(bool includeRelations)
    {
        var q = context.Set<AccessGroup>();

        if (includeRelations)
        {
            q.Include("AccessGroupAccessPoints");
        }

        return q.AsNoTracking().ToListAsync();
    }

解决方案

但我找到了一个解决方案,如果在它评估对象列表之前不拆分查询,Entity Framework 将包含预期的属性。 希望对你有帮助。

    public Task<List<AccessGroup>> GetAll(bool includeRelations)
    {
        if (includeRelations)
        {
            return context.Set<AccessGroup>()
                .Include(a => a.AccessGroupAccessPoints).ThenInclude(a => a.AccessPoint)
                .AsNoTracking()
                .ToListAsync();
        }
        else
        {
            return context.Set<AccessGroup>().AsNoTracking().ToListAsync();
        }
    }
    

问题

为什么会这样?

这是 Entity Framework 错误吗?

出于类似的原因,这不会对列表进行适当的排序:

var x = new List<int> { 3, 2, 1 };

x.OrderBy(i => i);

Console.WriteLine(string.Join("|", x));    //prints 3,2,1

您需要捕获并使用 OrderBy 的结果才能生效:

var x = new List<int> { 3, 2, 1 };

var y = x.OrderBy(i => i);

Console.WriteLine(string.Join("|", y));    //prints 1,2,3

在你的第一个代码中,你创建 q,然后你调用 Include(),但不要使用 Include 中的 return 值,并且 Include 不会修改q 这样它就变成了包含的东西(就像在列表上调用 OrderBy 不会摇晃它的项目所以它们是有序的)所以你包含的原因的知识丢失了..

..然而,在您的第二个代码中,当您 运行 查询(由于链)

时,您使用 Include 中的 return 值

也许您需要这样的东西:

public Task<List<AccessGroup>> GetAll(bool includeRelations)
{
    var q = context.AccessGroups.AsQueryable();    //so we can assign the IIncludableQueryable generated by Include.ThenInclude back to q

    if (includeRelations)
    {
        q = q.Include(a => a.AccessGroupAccessPoints)
            .ThenInclude(a => a.AccessPoint);
    }
    
    return q.ToListAsync();
}