C#/.NET 实体框架中的动态查询生成器

VSO*_*VSO 3 c# entity-framework

假设我们使用的db是 EF6 ,并且是 EF DbContext。假设用户可以输入五个可能的查询:

  1. 购买车龄等于 10 的汽车。
  2. 购买车龄小于 10 的汽车。
  3. 购买车龄超过 10 年的汽车。
  4. 购买车龄不等于 10 岁的汽车。
  5. 获取任何年龄的汽车。
    枚举运算符
    {
        平等的,
        不等于,    
        少于, 
        多于,
        任何
    };

    var operator = //某些用户选择的运算符,在上面枚举中可用的运算符中
    var carAge = //int 由用户选择以指定所需的年龄
    列出汽车; 

    开关(操作员)
    {
        case Operator.EQUAL 
        {
            汽车 = db.Cars.Where(c=> c.Age == carAge).ToList(); 
        }
        case Operator.NOT_EQUAL 
        {
            汽车 = db.Cars.Where(c=> c.Age != carAge).ToList(); 
        }
        case Operator.LESS_THAN 
        {
            汽车 = db.Cars.Where(c=> c.Age c.Age > carAge).ToList(); 
        }
        案例运算符.ANY 
        {
            汽车 = db.Cars.ToList(); 
        }
    }

我如何更有效地做到这一点?开关运算符看起来很傻。看起来这篇文章正在回答这个问题,但我并不完全理解。

我们确实有一个关于动态构建多个查询的答案,但这是我想要的不同部分(如果问题是“用户可以搜索车龄和里程,或者两者都不能搜索,则适用)”。

编辑:为了回应评论,我的“目标”是任何标准搜索,使用汽车示例,用户将有许多可以选择运营商的字段。他们可以使用任何、全部或不使用字段,例如

里程:运营商,价值
年份:运营商,价值
品牌:(例如/不是),汽车品牌

Che*_*hen 5

    Expression<Func<T, bool>> Build<T, TProperty>(Expression<Func<T, TProperty>> property, Operator op, TProperty value)
    {
        if (op == Operator.ANY)
        {
            return e => true;
        }

        var left = property.Body;   //you need to check if it's a valid property visit
        var right = Expression.Constant(value);
        BinaryExpression body;

        switch (op)
        {
            case Operator.EQUAL:
                body = Expression.Equal(left, right);
                break;
            case Operator.NOT_EQUAL:
                body = Expression.NotEqual(left, right);
                break;
            case Operator.LESS_THAN:
                //you'd better check if < operator is available for the type
                body = Expression.LessThan(left, right);
                break;
            case Operator.MORE_THAN:
                body = Expression.GreaterThan(left, right);
                break;
            default: throw new NotSupportedException();
        }

        return Expression.Lambda<Func<T, bool>>(body, property.Parameters[0]);
    }
Run Code Online (Sandbox Code Playgroud)

用法 var bmw = Build<Car, string>(c => c.Brand, Operator.EQUAL, "BMW");