65

重複したオブジェクトを含むデータを返す L2E クエリがあります。これらの重複オブジェクトを削除する必要があります。基本的に、それらの ID が同じである場合、オブジェクトは重複していると想定する必要があります。を試しましq.Distinct()たが、それでも重複したオブジェクトが返されました。次に、独自の IEqualityComparer を実装してDistinct()メソッドに渡してみました。メソッドは次のテキストで失敗しました:

LINQ to Entities はメソッド 'System.Linq.IQueryable 1[DAL.MyDOClass] Distinct[MyDOClass](System.Linq.IQueryable1[DAL.MyDOClass], System.Collections.Generic.IEqualityComparer`1[DAL.MyDOClass])' メソッドを認識せず、このメソッドはストア式に変換できません。

EqualityComparer の実装は次のとおりです。

  internal class MyDOClassComparer: EqualityComparer<MyDOClass>
    {
        public override bool Equals(MyDOClass x, MyDOClass y)
        {
            return x.Id == y.Id;
        }

        public override int GetHashCode(MyDOClass obj)
        {
            return obj == null ? 0 : obj.Id;
        }
    }

IEqualityComparerでは、自分自身を適切に書くにはどうすればよいでしょうか。

4

4 に答える 4

149

行く方法ではありません-メモリ内のEqualityComparer結果セットのみをフィルタリングできます。

var objects = yourResults.ToEnumerable().Distinct(yourEqualityComparer);

メソッドを使用しGroupByて ID でグループ化し、メソッドを使用しFirstてデータベースが ID ごとに一意のエントリのみを取得できるようにすることができます。

var objects = yourResults.GroupBy(o => o.Id).Select(g => g.First());
于 2011-12-19T11:52:45.923 に答える
21

rich.okelly と Ladislav Mrnka はどちらもさまざまな点で正しいです。

IEqualityComparer<T>どちらの回答も、のメソッドが SQL に変換されないという事実を扱っています。

それぞれの長所と短所を検討する価値があると思います。これにはコメント以上の時間がかかります.

リッチのアプローチは、クエリを別のクエリに書き直して、最終的な結果を同じにします。彼らのコードは多かれ少なかれ、手動でコーディングされた SQL でこれを効率的に行う方法を示しているはずです。

Ladislav's は、distinct の前の時点でデータベースからそれを引き出します。その後、インメモリ アプローチが機能します。

データベースは、リッチが依存する種類のグループ化とフィルタリングを行うのに優れているため、この場合、最もパフォーマンスが高い可能性があります。ただし、このグループ化の前に起こっていることの複雑さは、Linq-to-entities が単一のクエリを適切に生成するのではなく、一連のクエリを生成し、メモリ内で作業の一部を実行するようなものであることがわかります。かなり厄介かもしれません。

一般に、メモリ内のケースでは、グループ化は個別よりもコストがかかります (特に、AsList()ではなくを使用してメモリに取り込む場合AsEnumerable())。したがって、他の要件のためにこの段階ですでにメモリに取り込もうとしている場合は、パフォーマンスが向上します。

また、等価定義がデータベースで利用可能なものとうまく関連していない場合の唯一の選択肢でもあります。もちろん、IEqualityComparer<T>渡されたに基づいて等価定義を切り替えたい場合は、等価定義を切り替えることができます。パラメータ。

全体として、金持ちがここでの最良の選択である可能性が最も高いと私が言う答えですが、金持ちと比較してラディスラフの長所と短所が異なるため、勉強して検討する価値があります.

于 2011-12-19T12:18:59.837 に答える
9

あなたはしません。Distinct演算子はデータベースで呼び出されるため、アプリケーションで記述したコードは使用できません(等式コンパレータロジックをSQLに移動することはできません)。ただし、個別でない値をすべてロードして、アプリケーションで個別のフィルタリングを行うことに満足している場合を除きます。

var query = (from x in context.EntitySet where ...).ToList()
                                                   .Distinct(yourComparer);
于 2011-12-19T11:54:11.553 に答える