except節エンティティへのLINQとされたIEqualityComparerを使用して
-
21-09-2019 - |
質問
私はサブセットと比較してサブセットを除くすべてを選択するかを決定したいという実体を持っています。
このようなだから、私の質問になります。
Products.Except(ProductsToRemove(), new ProductComparer())
それはいくつかのタスクを実行した後、 ProductsToRemove()
方法はList<Product>
を返します。だからの最も単純な形式で、それは上だ。
このようなProductComparer()
クラスのルックスます:
public class ProductComparer : IEqualityComparer<Product>
{
public bool Equals(Product a, Product b)
{
if (ReferenceEquals(a, b)) return true;
if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
return false;
return a.Id == b.Id;
}
public int GetHashCode(Product product)
{
if (ReferenceEquals(product, null)) return 0;
var hashProductId = product.Id.GetHashCode();
return hashProductId;
}
}
しかし、私は継続的に次の例外を受け取ります:
認識していないエンティティへのLINQ 方法 「System.Linq.IQueryable
1[UnitedOne.Data.Sql.Product] Except[Product](System.Linq.IQueryable
1 [UnitedOne.Data.Sql.Product]、 System.Collections.Generic.IEnumerable1[UnitedOne.Data.Sql.Product], System.Collections.Generic.IEqualityComparer
1 [UnitedOne.Data.Sql.Product]「) 方法、およびこの方法にすることはできません 店舗の表現に翻訳ます。
解決
エンティティへのLINQのは、実際にクエリを実行していない、それは、サーバー上で実行することを、TSQLに変換します。
、の通訳のあなたのコードですはカバーの下には、演算子と共通の機能がどのように動作するかの知識とどのようにそれらTSQLに関連して符号化されます。問題は、L2Eの開発者は、あなたがたIEqualityComparerを実装しているか正確には分からないということです。したがって、彼らはあなたがクラスA == Bクラスを言うとき、あなたは(たとえば)「どこPerson.FirstName == FirstNameおよびPerson.LastName ==姓」。
を意味することを理解することはできませんだから、L2Eインタプリタは、それが認識しない方法に当たったとき、それはこの例外をスローします。
あなたはこれを回避することができる2つの方法があります。まず、あなたの平等の要件が、それを満たすには、任意のカスタムメソッドに依存しないことをどこで()を開発します。換言すれば、インスタンスの特性の等価性のテストではなく、クラスに定義されている方法に等しい。
第二に、あなたは、クエリの実行をトリガして、メモリのあなたの比較を行うことができます。たとえばます:
var notThisItem = new Item{Id = "HurrDurr"};
var items = Db.Items.ToArray(); // Sql query executed here
var except = items.Except(notThisItem); // performed in memory
これは明らかに、ワイヤ全体でより多くのデータを持参し、より多くのメモリを大量になります。最初のオプションは、通常は最高です。
他のヒント
あなたは、Entity SQLへのカスタムExcept
とIEqualityComparer
コールを変換しようとしている。
もちろん、あなたのクラスは、SQLに変換することはできません。
あなたは、クライアント上で実行することを強制するためにProducts.AsEnumerable().Except(ProductsToRemove(), new ProductComparer())
を記述する必要があります。これは、サーバからの製品のすべてをダウンロードすることに注意してください。
ところで、あなたのProductComparer
クラスは、このように、シングルトンである必要があります:
public class ProductComparer : IEqualityComparer<Product> {
private ProductComparer() { }
public static ProductComparer Instance = new ProductComparer();
...
}
IEqualityComparer<T>
のみローカルに実行することができ、それは、SQLコマンドに変換することができない、したがって、エラー