我需要构建一个查询,以根据过滤器值返回单个实体。它必须在服务器上执行,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实体中使用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类型的参数。 因此,在将其传递给StringConvert方法之前,我需要能够将propParam(一个整数)的值转换为double。 我该怎么做呢?
如果我可以编写查询,它就会像这样(这样可行):
var result = Repository.Query<Customer>().Where(x => SqlFunctions.StringConvert((double)x.Id) == Model.FilterValue);
使用动态LINQ来执行此操作或编写原始SQL查询可能更容易,但我想知道是否有一种解决方案,就像我先尝试一样。
答案 0 :(得分:1)
您可以使用int
将double
转换为表达式中的Expression.Convert
:
var param = Expression.Parameter(typeToLookUp, "x");
var property = Expression.Property(param, propParam);
var doubleValue = Expression.Convert(property, typeof(double));
var bodyLeft = Expression.Call(stringConvertMethod, doubleValue);