我想在 EF 6.0 中使用代码优先方法为 sql IN 子句创建一个动态 linq 表达式。请注意,我是表达式的新手。我想要达到的是
select * from Courses where CourseId in (1, 2, 3, 4)
//CourseId is integer
正常的 linq 查询如下所示。但我想动态查询它
string[] ids = new string[]{"1", "2", "3", "4"};
var courselist = DBEntities.Courses.Where(c => ids.Contains(SqlFunctions.StringConvert((decimal?)c.CourseId)))
动态表达有两种方式。
1) 一种方法是遍历 ids 并制作表达式
下面的代码将在调试视图中创建以下表达式
{f => ((StringConvert(Convert(f.CourseId)).Equals("23") Or StringConvert(Convert(f.CourseId)).Equals("2")) Or StringConvert(Convert(f.CourseId)).Equals("1"))}
动态表达式是
var param = Expression.Parameters(typeof(Course), "f")
MemberExpression property = Expression.PropertyOrField(param, "CourseId");
MethodInfo mi = null;
MethodCallExpression mce = null;
if (property.Type == typeof(int))
{
var castProperty = Expression.Convert(property, typeof(double?));
var t = Expression.Parameter(typeof(SqlFunctions), "SqlFunctions");
mi = typeof(SqlFunctions).GetMethod("StringConvert", new Type[] { typeof(double?) });
mce = Expression.Call(null,mi, castProperty);
}
mi = typeof(string).GetMethod("Equals", new Type[]{ typeof(string)});
BinaryExpression bex = null;
if (values.Length <= 1)
{
return Expression.Lambda<Func<T, bool>>(Expression.Call(mce, mi, Expression.Constant(values[0]), param));
}
//var exp1 = Expression.Call(mce, mi, Expression.Constant(values[0]));
for (int i = 0; i < values.Length; i++)
{
if (bex == null)
{
bex = Expression.Or(Expression.Call(mce, mi, Expression.Constant(values[i])), Expression.Call(mce, mi, Expression.Constant(values[i + 1])));
i++;
}
else
bex = Expression.Or(bex, Expression.Call(mce, mi, Expression.Constant(values[i])));
}//End of for loop
return Expression.Lambda<Func<T, bool>>(bex, param);
2)我尝试的第二种方式(调试视图)
{f => val.Contains("23")} //val is parameter of values above
我试过的上面的动态表达式是
var param = Expression.Parameters(typeof(Course), "f")
MemberExpression property = Expression.PropertyOrField(param, "CourseId");
var micontain = typeof(Enumerable).GetMethods().Where(m => m.Name == "Contains" && m.GetParameters().Length == 2).Single().MakeGenericMethod(typeof(string));
var mc = Expression.Call(micontain, Expression.Parameter(values.GetType(), "val"), Expression.Constant("2"));//NOTE: I haven't use CourseId for now as i am getting conversion error
return Expression.Lambda<Func<T, bool>>(mc, param);
我收到以下错误
- LINQ to Entities 无法识别“System.String StringConvert(System.Nullable`1[System.Double])”方法,当我使用第一种方法时,该方法无法转换为存储表达式。我知道我不能将 ToString 与 EF 一起使用,这就是我使用 SqlFunctions 的原因,但它对我不起作用。
- 使用第二种方法,参数“val”未绑定在指定的 LINQ to Entities 查询表达式中
我从过去 4 天开始尝试这个。我用谷歌搜索了它,但没有找到任何合适的解决方案。请帮我。