在鞭打互联网之后,我无法找到可以开始工作的解决方案。我试图使用动态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; }
}
大多数都是自我解释的,但操作员和操作员符号之间的区别在于操作员将存储"等于"或者"大于"操作符号将在哪里" =="和">"分别。 AndOR以类似的方式工作。
然后,当用户构建where子句时,会创建一个新的WhereClause对象并将其添加到List<WhereClause>
当运行查询时,我正在使用实体框架和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"
格式化谓词但未找到正确的方法。
所以现在我转向你们寻求帮助..
答案 0 :(得分:1)
您需要将WhereClause
对象翻译为Expression
,然后您可以将其用作查询位置。这是一个例子:
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);