带有列表的表达式函数<;T>;.选择().Contains()

本文关键字:Contains gt 选择 lt 列表 表达式 函数 | 更新日期: 2023-09-27 17:59:55

这是我的通用存储库类方法:

public IEnumerable<T> GetBy(Expression<Func<T, bool>> condition)
    {
        return Context.Set<T>().Where(condition).ToList();
    }

我想这样称呼它:

resultCandidate = _repo.GetBy(p => members.Select(s=>s.MemberID).Contains(p.CandidateMemberID)).ToList();

但当我尝试它时,它抛出了一个错误,比如"无法创建StateInfo类型的常数值。在这种情况下,只支持基元类型或枚举类型。"

我应该这样调用这个方法。我试着condition.Compile(),它起到了作用,但没有达到我想要的效果。因为它在生成SQL查询时没有得到where子句。

注:会员为List<MemberInfo>

感谢

带有列表的表达式函数<;T>;.选择().Contains()

您的方法是可以的。但您需要将成员ID列表移动到表达式之外(这就是异常消息试图指示的),从而满足基元类型列表要求:

var memberIds = members.Select(s=>s.MemberID).ToList();
resultCandidate = _repo.GetBy(p => memberIds.Contains(p.CandidateMemberID)).ToList();

更新:好吧,如果准确地这样称呼它对你来说非常重要,那么你可以尝试以下非常天真的ExpressionVisitor:

using System.Linq.Expressions;
class ExpandSelectVisitor : ExpressionVisitor
{
    protected override Expression VisitMethodCall(MethodCallExpression node)
    {
        if (node.Method.DeclaringType == typeof(Enumerable) && node.Method.Name == "Select")
            return Expression.Constant(Expression.Lambda(node).Compile().DynamicInvoke());
        return base.VisitMethodCall(node);
    }
}

并在通用存储库中使用它,方法如下:

public IEnumerable<T> GetBy(Expression<Func<T, bool>> condition)
{
    condition = condition.Update(
        new ExpandSelectVisitor().Visit(condition.Body), condition.Parameters);
    return Context.Set<T>().Where(condition).ToList();
}