将过滤后的包含附加到表达式

Append Filtered Include to Expression

在我们的项目中,我们的数据库中存储了多种语言的文本。 我想创建一个在查询中包含文本的辅助函数。

这会很有用,因为这种包含在应用程序中经常发生,我希望将包含代码放在一个地方。

包含应该使用 Entity Framework Core 5 中的 the new filtered includes

这是我要替换的:

.Include(c => c.NameTexts.Where(t => t.LanguageId == langId))

替换为:

.IncludeText(e => e.NameTexts, langId)

我要写的功能:

// The helper function:
public static IQueryable<T> IncludeText<T>(this IQueryable<T> originalQuery, Expression<Func<T, IEnumerable<UserText>>> textToInclude, int langId) where T : class
{
     var textWhere = textToInclude.Where(e => e.LanguageId == langId);
     originalQuery.Include(textWhere);
     return originalQuery;
}

// And call it from a query like this:
var result = await _context.SomeEntity
                .IncludeText(e => e.NameTexts, langId)
                // Instead of
                // .Include(c => c.NameTexts.Where(t => t.LanguageId == langId))
                .Where(c => c.Id == request.Id)
                .SingleOrDefaultAsync(cancellationToken);

我尝试执行以下操作但出现错误,因为类型不匹配。

Expression<Func<UserText, bool>> newPred = t => t.LanguageId == langId;
var textWhere = Expression.Lambda<Func<T, IList<UserText>>>(Expression.AndAlso(textToInclude, newPred), textToInclude.Parameters);

originalQuery.Include(textWhere);
return originalQuery;

也许这行得通:

public static IQueryable<T> IncludeText<T>(this IQueryable<T> originalQuery, Expression<Func<T, IEnumerable<UserText>>> textToInclude, int langId) where T : class
{
    var methodWhere = typeof(Enumerable)
        .GetMethods()
        .First(m => m.ToString() == "System.Collections.Generic.IEnumerable`1[TSource] Where[TSource](System.Collections.Generic.IEnumerable`1[TSource], System.Func`2[TSource,System.Boolean])")
        .MakeGenericMethod(typeof(UserText));
    Expression<Func<UserText, bool>> predicate = t => t.LanguageId == langId;
    var navigationWhere = Expression.Call(methodWhere, textToInclude.Body, predicate);
    var lambda = Expression.Lambda<Func<T, IEnumerable<UserText>>>(navigationWhere, Expression.Parameter(typeof(T)));
    return originalQuery.Include(lambda);
}

我不喜欢 Where MethodInfo 的恢复方式。您可以通过其他 question.

的启发来改进