Entity Framework 列表中的动态 Where 子句<object>

Entity Framework Dynamic Where Clause from List<object>

在互联网上搜索之后,我一直无法找到可以开始工作的解决方案。我正在尝试使用动态 linq 使用户能够从 windows 表单构建自定义查询。为了保存每个 where 子句,我构建了一个名为 WhereClause 的对象:

public class WhereClause
{
    public int id { get; set; }
    public string ColumnName { get; set; }
    public string Operator { get; set; }
    public string OperatorSymbol { get; set; }
    public object Value { get; set; }
    public string AndOr { get; set; }
    public string AndOrSymbol { get; set; }
}

大多数是不言自明的,但是运算符和运算符符号之间的区别在于运算符将 "Equals" 或 "Greater Than" 存储到运算符符号为“==”和“>”的位置分别。 AndOR 以类似的方式工作。

然后当用户构建 where 子句时,会创建一个新的 WhereClause 对象并将其添加到 List<WhereClause>

当需要 运行 查询时,我正在使用 entity framework 和 linq 来构建查询。

我想做这样的事情:

List<WhereClause> wheres; //populated via parameter in the encapsulating method.

DataContext db = new DataContext();
var query = from d in db.Database select d;

string whereClause = "";

foreach(WhereClause where in wheres){
    whereClause = whereClause + String.Format(" {0} {1} {2} {3}", where.ColumnName, where.OperatorSymbol, where.Value, where.AndOrSymbol);

    query.Where(whereClause);

}

我尝试了各种构建 where 子句的方法,包括使用 where(predicate, params) 和使用 "@1" 格式化谓词,但还没有找到正确的方法。

这是上下文的查询构建器的样子..

所以现在我转向你们寻求帮助..

您需要将您的 WhereClause 对象翻译成 Expression,然后您可以将其用作 where 查询。举个例子:

Type yourType = typeof(YourGeneric);
ParameterExpression pe = Expression.Parameter(yourType , "x");
Expression left = Expression.Property(pe, yourType.GetProperty(whereClause.ColumnName));
Expression right = Expression.Constant(whereClause.Value, typeof(int));
Expression result = Expression.Equal(left, right);

这是一个比较 int 属性 的例子。您需要一些 if(或 switch)来了解 属性 类型以及您需要进行的比较类型。

if (whereClause.Operator == "Greater Than") {
    result = Expression.GreaterThan(left, right);
}

当您以这种方式完成使用 Expression 时:

context.Set<YourGeneric>().Where(result);

我建议使用泛型(如果可能的话)来简化代码和工作。 您还可以连接更多表达式:

Expression result4 = Expression.AndAlso(result1, result2);
Expression finalRes = Expression.Or(result3, result4);