我需要构造一个查询以根据过滤器值返回单个实体。它必须在服务器上执行,LINQ 2 Objects 不是一个选项。
要返回的实体的类型、获取它的属性以及该属性的值都只在运行时知道并且可以在运行时更改,所以我需要尽可能动态地执行此操作。我觉得我快到了,但最后一步一直在躲避我。这是我到目前为止所尝试的:
模型包含过滤器数据
propParam将始终是int类型
propModel将始终为字符串类型
我无法更改这些类型,因为这只是众多过滤方案(查找)之一。
private void SetFilter(Type typeToLookUp, string filterPropertyName)
{
var propParam = typeToLookUp.GetProperty(filterPropertyName);
var propModel = Model.GetType().GetProperty("FilterValue");
var param = Expression.Parameter(typeToLookUp, "x");
var bodyLeft = Expression.Property(param, propParam);
var bodyRight = Expression.Property(Expression.Constant(Model), propModel);
var body = Expression.Equal(bodyLeft, bodyRight);
...
}
这当然会失败,因为我试图将一个 int(左)与一个字符串(右)进行比较。
所以我需要将 int 转换为字符串以便能够比较它,在 LINQ 2 Entities SqlFunctions.StringConvert 中使用:
private void SetFilter(Type typeToLookUp, string filterPropertyName)
{
var propParam = typeToLookUp.GetProperty(filterPropertyName);
var propModel = Model.GetType().GetProperty("FilterValue");
var stringConvertMethod = typeof(SqlFunctions).GetMethods(BindingFlags.Public | BindingFlags.Static)
.Single(
x =>
x.Name == "StringConvert" && x.GetParameters().Count() == 1 &&
x.GetParameters()[0].ParameterType == typeof(double?));
var param = Expression.Parameter(typeToLookUp, "x");
var bodyLeft = Expression.Call(stringConvertMethod, Expression.Property(param, propParam));
...
}
当然这个方法调用会失败,因为 StringConvert 不接受 int 类型的参数。因此,在将 propParam(整数)的值传递给 StringConvert 方法之前,我需要能够将其转换为 double。我该怎么做呢?
例如,如果我可以编写查询,它将如下所示(这有效):
var result = Repository.Query<Customer>().Where(x => SqlFunctions.StringConvert((double)x.Id) == Model.FilterValue);
也许只使用动态 LINQ 来执行此操作会更容易,或者编写一个原始 SQL 查询,但我想知道是否有我首先尝试的解决方案。