Entity Frameworkバージョン4を使用しています。大きな(〜100万レコード)SQL Serverテーブルを、Webサービスから返される長い(〜2000)複雑なオブジェクトの配列と比較する必要があります。複雑なオブジェクトのインスタンスがすでにデータベースにあるかどうかを判断するには、5つの異なるプロパティを比較する必要があります。
.Whereメソッドと.Anyメソッドで使用する式を返す関数を作成しました。次のようになります(Aは複雑なオブジェクト、tblAはEFクラス)。
function Expression<tblA, bool> GetSearchPredicate(A a)
{
return ta => ta.Field1.Equals(a.Field1)
&& ta.Field2.Equals(a.Field2)
&& ta.Field3.Equals(a.Field3)
&& ta.Field4.Equals(a.Field4)
&& ta.Field5.Equals(a.Field5);
}
これは機能します。そして、これを行うことで、Aの2000個のインスタンスすべてを比較できます。
IEnumerable<A> objects = [web service call];
var result = objects.Select(a => !db.tblA.Any(GetSearchPredicate(a)));
それもうまくいきます。しかし、それは遅いです。そこで、EFを介してデータベースに直接送信できる式を作成できるユーティリティメソッドの作成を検討しました。
この質問のコードを、そのユーティリティメソッドを構築するための基礎として使用しました。その質問の例は、単一のプロパティを一連の定数と比較することを示していますが、私のバージョンでは、複数のプロパティを複数の定数と比較する必要があります。私の最善の努力は以下の通りです:
public static IQueryable<TEntity> WhereIn<TEntity>
(
this ObjectQuery<TEntity> query,
IEnumerable<Expression<Func<TEntity, bool>>> predicates
)
{
if (predicates == null) throw new ArgumentNullException("predicates");
IEnumerable<ParameterExpression> p = predicates.Select(pred => pred.Parameters.Single()).ToArray();
IEnumerable<Expression> equals = predicates.Select(value =>
(Expression)value.Body);
Expression bigEqual = equals.Aggregate((accumulate, equal) =>
Expression.Or(accumulate, equal));
var result1 = Expression.Lambda<Func<TEntity, bool>>(bigEqual, p.First());
var result = query.Where(result1);
return result;
}
これは次のように呼び出されます。
IEnumerable<A> objects = [web service call];
var result = db.tblA.WhereIn(objects.Select(a => GetSearchPredicate(a)));
「ta」(TEntityオブジェクトのプレースホルダー)がバインドされていないというメッセージが表示されます。これは、複数の式(変数)が組み合わされているためだと思いました。おそらく、 IEnumerablepredicates
の最初のパラメーターのみを渡したために、このメッセージがスローされていました。predicates
ただし、これpredicates
は1つの式の長さであっても発生します。
A.Field1
リンクしたメソッドに基づいて、5つのプロパティのそれぞれを定数(からの値)と比較する式を作成できると確信しています。既に一連のプロパティにアセンブルされているA.Field5
パラメーターを渡すのではありません。predicates
式。しかし、私はむしろそうしません。なぜなら、それはタイプA
とtblA
で動作していることを知るための私のメソッドを必要とし、それは汎用と汎用の反対です。(これも複雑で面倒です。)
私が示した例が私がやりたいことを説明することを願っています。それは一般的な方法で行うことができますか?