.NET Core仓储模式中Where子句后Select表达式的类型转换错误问询
问题分析与解决办法
你的编译错误根源是错误使用了Select(expression):
你传入的expression是Expression<Func<T, bool>>类型(用于筛选条件,返回布尔值),但Select方法需要的是Expression<Func<T, TResult>>类型的投影器(用来从T类型对象中提取指定结果)。当你写.Select(expression)时,会把每个T实体转换成bool值,最终得到IQueryable<bool>,但你的方法签名要求返回IQueryable<T>,类型不匹配才抛出了转换错误。
从你的需求和示例代码来看,你应该是想控制查询是否启用实体变更跟踪,而非在这个方法里做字段投影。EF中关闭变更跟踪的正确方式是调用AsNoTracking()方法,而非错误使用Select。
修正后的RepositoryBase实现代码:
public IQueryable<T> GetRelationData(Expression<Func<T, bool>> expression, bool trackChanges) { var baseQuery = RepositoryContext.Set<T>().Where(expression); return trackChanges ? baseQuery : baseQuery.AsNoTracking(); }
如果之后你需要在这个方法里支持字段投影(就像你示例中获取RateId那样的操作),可以给接口和实现新增一个重载方法:
// IRepositoryBase接口新增重载 IQueryable<TResult> GetRelationData<TResult>(Expression<Func<T, bool>> filterExpression, Expression<Func<T, TResult>> selectExpression, bool trackChanges); // RepositoryBase中的实现 public IQueryable<TResult> GetRelationData<TResult>(Expression<Func<T, bool>> filterExpression, Expression<Func<T, TResult>> selectExpression, bool trackChanges) { var query = RepositoryContext.Set<T>().Where(filterExpression).Select(selectExpression); return trackChanges ? query : query.AsNoTracking(); }
这样调用时就能同时完成筛选、投影和变更跟踪控制,和你给出的EF示例逻辑对齐。
内容的提问来源于stack exchange,提问作者BlackMamba
相关产品推荐
相关产品推荐

