You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Generic Repository模式下如何实现支持ThenIncludes的关联查询

方案1:使用字符串路径实现(实现成本最低)

EF原生支持字符串形式的级联关联路径加载,你只需要重载AsQueryable方法接收字符串参数即可,上层调用完全不需要依赖EF相关的包,符合你的分层约束。

代码改造

// 新增字符串路径的重载
/// <inheritdoc/>
public IQueryable<T> AsQueryable(params string[] includePaths)
{
    var query = _dbSet.AsQueryable();
    if (includePaths != null)
    {
        query = includePaths.Aggregate(query, (current, path) => current.Include(path));
    }
    return query;
}

// 保留原有表达式重载,兼容旧代码
/// <inheritdoc/>
public IQueryable<T> AsQueryable(params Expression<Func<T, object>>[] includes)
{
    var query = _dbSet.AsQueryable();
    if (includes != null)
    {
        query = includes.Aggregate(query, (current, include) => current.Include(include));
    }
    return query;
}

调用示例

// 直接传入多级关联的完整路径即可,也可以分开传"Books"、"Books.Author"
var query = _repository.AsQueryable("Books.Author");

方案2:封装强类型级联Include(类型安全无魔法字符串)

如果你希望保留编译期类型校验,避免写错字符串,可以自行封装一套不依赖EF的强类型Include语法,仅在DataAccess层做EF兼容转换即可。

第一步:在公共抽象层定义通用Include结构(不需要引用EF)

// 导航属性包含路径的封装结构
public class IncludeExpression<T>
{
    internal List<LambdaExpression> PathSegments { get; } = new();
}

// 通用扩展方法,和EF完全解耦
public static class IncludeExtensions
{
    public static IncludeExpression<T> Include<T, TProperty>(this Expression<Func<T, TProperty>> rootExpr)
    {
        var include = new IncludeExpression<T>();
        include.PathSegments.Add(rootExpr);
        return include;
    }

    public static IncludeExpression<T> ThenInclude<T, PreviousType, CurrentType>(this IncludeExpression<T> include, Expression<Func<PreviousType, CurrentType>> nextExpr)
    {
        include.PathSegments.Add(nextExpr);
        return include;
    }
}

第二步:在DataAccess层新增对应重载的实现

/// <inheritdoc/>
public IQueryable<T> AsQueryable(params IncludeExpression<T>[] includes)
{
    var query = _dbSet.AsQueryable();
    if (includes == null) return query;
    
    foreach (var include in includes)
    {
        // 把自定义的路径段转换成EF的Include/ThenInclude调用
        dynamic currentQuery = query.Include(include.PathSegments[0]);
        for (int i = 1; i < include.PathSegments.Count; i++)
        {
            currentQuery = EntityFrameworkQueryableExtensions.ThenInclude(currentQuery, include.PathSegments[i] as dynamic);
        }
        query = currentQuery;
    }
    return query;
}

调用示例

// 强类型调用,属性不存在编译期就会报错
var query = _repository.AsQueryable(
    e => e.Books.Include().ThenInclude<你的主实体类型, Book, Author>(b => b.Author)
);

两种方案都完全满足「EntityFramework仅在DataAccess层被引用」的分层要求,可以根据项目的实际需求选择。


内容的提问来源于stack exchange,提问作者Filipe Nóbrega

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 12:18:03