データベースにStuffという名前のプロパティがあり、Idというプロパティがあるとします。ユーザーから、選択したRangeオブジェクトのシーケンスを取得します(または、入力から作成します)。必要なIDを使用します。その構造体の簡略版は次のようになります。
public struct Range<T> : IEquatable<Range<T>>, IEqualityComparer<Range<T>>
{
public T A;
public T B;
public Range(T a, T b)
{
A = a;
B = b;
}
...
}
したがって、たとえば、次のようになります。
var selectedRange = new List<Range<int>>
{
new Range(1, 4),
new Range(7,11),
};
次に、それを使用して、それらの間に値を持つものだけを選択する述語を作成したいと思います。たとえば、PredicateBuilderを使用すると、たとえば次のように実行できます。
var predicate = PredicateBuilder.False<Stuff>();
foreach (Range<int> r in selectedRange)
{
int a = r.A;
int b = r.B;
predicate = predicate.Or(ø => ø.Id >= a && ø.Id <= b);
}
その後:
var stuff = datacontext.Stuffs.Where(predicate).ToList();
どちらがうまくいくか!私が今やりたいのは、これらの述語を作成するためのジェネリック拡張メソッドを作成することです。このようなもの:
public static Expression<Func<T,bool>> ToPredicate<T>(this IEnumerable<Range<int>> range, Func<T, int> selector)
{
Expression<Func<T, bool>> p = PredicateBuilder.False<T>();
foreach (Range<int> r in range)
{
int a = r.A;
int b = r.B;
p = p.Or(ø => selector(ø) >= a && selector(ø) <= b);
}
return p;
}
ここでの問題は、selector(ø)呼び出しが原因でNotSupportedExceptionでクラッシュすることです。Method 'System.Object DynamicInvoke(System.Object[])' has no supported translation to SQL.
それは理解できると思います。しかし、これを回避する方法はありますか?私が最終的にやりたいのは、私ができるようにすることです。
var stuff = datacontext.Stuffs.Where(selectedRange.ToPredicate<Stuff>(ø => ø.Id));
または、さらに良いことに、IQueryableを返すものを作成して、次のことを実行できるようにします。
var stuff = datacontext.Stuffs.WhereWithin<Stuff>(selectedRange, ø => ø.Id); // Possibly without having to specify Stuff as type there...
それで、何かアイデアはありますか?私は本当にこれを機能させたいと思っています。そうでない場合は、コードのforeachブロックをたくさん取得して、述語を作成します...
注1:もちろん、DateTimeなどのようにint以上に拡張できればいいのですが、>=および<=演算子を使用するとどうなるかわかりません...CompareToはlinq-to-で機能しますかsql?そうでない場合は、2つ作成しても問題ありません。1つはint用、もう1つはDateTime用です。これは、ほとんどの場合、これが使用される型であるためです。
注2:レポートに使用され、ユーザーはさまざまなことに基づいて、何が出るかを絞り込むことができます。同様に、私はそれらの人々とそれらの日付のためにこのレポートが欲しいです。