我正在使用规范模式来执行数据库过滤,并避免在内存上进行(我大致遵循了这篇文章)。我的基本规范类是这样的:
public abstract class Specification<T> : ISpecification<T>{
public abstract Expression<Func<T, bool>> FilterExpr();
public bool IsSatisfied(T entity)
{
Func<T, bool> func = this.FilterExpr().Compile();
return func(entity);
}
public Specification<T> And(Specification<T> otherSpec)
{
return new CombinedSpecification<T>(this, otherSpec);
}
}
从这个基本规范类,派生出多个强类型规范,它们各自工作得很好。但是,当尝试组合这些规范并在我的 Repository 类中评估 CombinedSpecification 时,就会出现问题:
System.InvalidOperationException:无法翻译 LINQ 表达式 'DbSet() .Where(c => c.ClientCode == __client_0 && c.Status == "Efective")'。以可翻译的形式重写查询,或通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用显式切换到客户端评估。有关详细信息,请参阅https://go.microsoft.com/fwlink/?linkid=2101038。
下面看一下 CombinedSpecification 类:
internal class CombinedSpecification<T> : Specification<T>
{
private Specification<T> leftSpec;
private Specification<T> rightSpec;
public CombinedSpecification(Specification<T> aSpec, Specification<T> otherSpec)
{
this.leftSpec = aSpec;
this.rightSpec = otherSpec;
}
public override Expression<Func<T, bool>> FilterExpr()
{
Expression<Func<T, bool>> firstExpr = this.leftSpec.FilterExpr();
Expression<Func<T, bool>> secondExpr = this.rightSpec.FilterExpr();
BinaryExpression combined = Expression.AndAlso(firstExpr.Body, secondExpr.Body);
return Expression.Lambda<Func<T, bool>>(combined, firstExpr.Parameters.Single());
}
}
为了清楚起见,按单个规范过滤就可以了,但是在组合它们时,LinQ 表达式似乎无法翻译(这对我来说似乎很奇怪,因为我没有使用 SQL AFAIK 不支持的任何方法)。我避免显示 Repository 类以减少此问题的数量,但无论如何,这里是我的 Find() 方法的相关行:
public IEnumerable<TEntity> Find(Specification<TEntity> spec)
{
IQueryable<TEntity> result = this.dbSet;
if (spec != null)
{
result = result.Where(spec.FilterExpr());
}
return result.ToList();
}
提前感谢您的帮助,我希望我的第一个问题已经明确说明!