5

サブセットと比較して、サブセット以外のすべてを選択することを決定したいエンティティがあります。

したがって、私のクエリは次のようになります。

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 to Entities はメソッド 'System.Linq.IQueryable 1[UnitedOne.Data.Sql.Product] Except[Product](System.Linq.IQueryable1[UnitedOne.Data.Sql.Product], System.Collections.Generic.IEnumerable 1[UnitedOne.Data.Sql.Product], System.Collections.Generic.IEqualityComparer1[UnitedOne.Data.Sql.Product])' メソッドを認識せず、このメソッドは認識できませんストア表現に変換されます。

4

3 に答える 3

8

Linq to Entities は実際にクエリを実行するのではなく、コードを解釈して TSQL に変換し、それをサーバー上で実行します。

内部的には、演算子と一般的な関数がどのように動作するか、およびそれらが TSQL とどのように関連するかについての知識を使用してコーディングされています。問題は、L2E の開発者が IEqualityComparer をどの程度正確に実装しているかを知らないことです。Class A == Class Bしたがって、あなたが(たとえば)のことを言っているとき、彼らはそれを理解できません"Where Person.FirstName == FirstName AND Person.LastName == LastName"

そのため、L2E インタープリターが認識できないメソッドにヒットすると、この例外がスローされます。

これを回避するには 2 つの方法があります。まず、Where()等式要件を満たすが、カスタム メソッドに依存しない a を開発します。Equalsつまり、クラスで定義されたメソッドではなく、インスタンスのプロパティが等しいかどうかをテストします。

次に、クエリの実行をトリガーして、メモリ内で比較を行うことができます。例えば:

var notThisItem = new Item{Id = "HurrDurr"};
var items = Db.Items.ToArray(); // Sql query executed here
var except = items.Except(notThisItem); // performed in memory

明らかに、これはより多くのデータをネットワーク経由で転送し、より多くのメモリを消費します。通常、最初のオプションが最適です。

于 2010-01-20T16:26:56.573 に答える
4

Exceptカスタムの呼び出しをIEqualityComparerEntity SQLに変換しようとしています。

明らかに、クラスを SQL に変換することはできません。

Products.AsEnumerable().Except(ProductsToRemove(), new ProductComparer())クライアントで強制的に実行するには、書き込む必要があります。これにより、サーバーからすべての製品がダウンロードされることに注意してください。


ちなみに、ProductComparerクラスは次のようにシングルトンにする必要があります。

public class ProductComparer : IEqualityComparer<Product> {
    private ProductComparer() { }
    public static ProductComparer Instance = new ProductComparer();

    ...
}
于 2010-01-20T16:20:51.980 に答える
3

IEqualityComparer<T>ローカルでのみ実行でき、SQL コマンドに変換できないため、エラーが発生します

于 2010-01-20T16:21:39.020 に答える