コードファーストアプローチを使用して、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)))
動的な表現を作成するには、2 つの方法があります。
1) 1 つの方法は、ID をループして式
を作成することです。以下のコードは、デバッグ ビューで次の式を作成します。
{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)私が試した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 クエリ式で2 番目の方法を使用してバインドされませんでした
私は過去4日間からこれを試しています。私はそれをグーグルで検索しましたが、適切な解決策が見つかりませんでした。私を助けてください。