OrderBy子句阻止加载导航属性

时间:2018-03-10 19:19:48

标签: c# entity-framework-core ef-core-2.0

我正在投资组合网站上,在产品页面上,我想显示同一类别的相关文章。

我创建了一种方法,允许我随机选择已定义类别的文章。不幸的是,当我添加OrderBy子句以“启用”随机性时,我将无法再检索导航属性。

public async Task<IEnumerable<Article>> GetRandomArticlesByCategoryIdAsync(int categoryId, int numberOfArticles)
{
    return await _ptitsBricosContext
        .Articles
        .OrderBy(a => Guid.NewGuid())
        .Include(a => a.Pictures)
        .Where(a => a.Category.Id == categoryId)
        .Take(numberOfArticles)
        .ToListAsync();
}

当我删除.OrderBy(a => Guid.NewGuid())时,我正确地检索了相关的Pictures,但是当我再次添加它时,我总是检索一个空的图片列表(即使我总是有结果)。

我有点卡住,我不明白为什么它会改变请求的行为。

1 个答案:

答案 0 :(得分:2)

此问题是由随机订单,Take运算符和子集合Include的组合引起的。

EF Core使用单独的数据库查询处理集合Include,将主查询与相关表连接起来。

由于此方案中的主查询返回不同的记录,因此第二个查询连接不会返回第一个查询结果的相关记录。相关集合可能为空或部分填充。

不幸的是,我认为这种情况没有好的解决方法。考虑将其发布到他们的GitHub问题跟踪器,看看他们会说些什么。

我看到的唯一相对有效的解决方法是修改主查询以仅返回PK,执行它并使用列表作为实际查询的条件:

var ids = await _ptitsBricosContext
    .Articles
    .OrderBy(a => Guid.NewGuid())
    .Where(a => a.Category.Id == categoryId)
    .Take(numberOfArticles)
    .Select(a => a.Id)
    .ToListAsync();

return await _ptitsBricosContext
    .Articles
    .Include(a => a.Pictures)
    .Where(a => ids.Contains(a.Id))
    .ToListAsync();