0

私は次のエンティティモデルを持っています。簡潔にするために、各エンティティの多くのプロパティを省略しました。

public sealed class Platform {
    /// <summary>
    /// Get and Set Platform's Unique Identifier.
    /// </summary>
    public int Id { get; set; }

    /// <summary>
    /// Determine if an Object is Equal to This Platform.
    /// </summary>
    /// <param name="obj">
    /// An object to compare.
    /// </param>
    /// <returns>
    /// A boolean true if the object is equal to this platform. A boolean false otherwise.
    /// </returns>
    public override bool Equals(object obj) {
        bool isObjectPlatform = obj is Platform;
        bool isObjectIdEqual = isObjectPlatform && (obj as Platform).Id == this.Id;

        return isObjectIdEqual;
    }

    /// <summary>
    /// Get Platform's Hash Code.
    /// </summary>
    /// <returns>
    /// The platform's hash code, equalling the platform's unique identifier.
    /// </returns>
    public override int GetHashCode() {
        return this.Id;
    }
}

public sealed class Capture {
    /// <summary>
    /// Get and Set Capture's Unique Identifier.
    /// </summary>
    public int Id { get; set; }

    /// <summary>
    /// Get and Set Capture's Platform.
    /// </summary>
    public Platform Platform { get; set; }

    /// <summary>
    /// Determine if an Object is Equal to This Capture.
    /// </summary>
    /// <param name="obj">
    /// An object to compare.
    /// </param>
    /// <returns>
    /// A boolean true if the object is equal to this capture. A boolean false otherwise.
    /// </returns>
    public override bool Equals(object obj) {
        bool isObjectCapture = obj is Capture;
        bool isObjectIdEqual = isObjectCapture && (obj as Capture).Id == this.Id;

        return isObjectIdEqual;
    }

    /// <summary>
    /// Get Capture's Hash Code.
    /// </summary>
    /// <returns>
    /// The capture's hash code, equalling the capture's unique identifier.
    /// </returns>
    public override int GetHashCode() {
        return this.Id;
    }
}

基本的に必要なのは、EFによってバックアップされたLINQクエリです。これにより、プラットフォームエンティティ全体でグループ化されたキャプチャの数を取得できます。プロパティの1つではなく、各プラットフォームへの参照と、それに関連付けられている各キャプチャの数を返すことができるようにしたいと思います。

私はこのクエリを実行しましたが、うまく機能します。

var query = this._defaultContext.Captures
                .Include(m => m.Platform)
                .GroupBy(m => m.Platform.Id)
                .Select(m => new {
                    PlatformId = m.Key,
                    Count = m.Count()
                });

しかし、ご覧のとおり、私はプラットフォームの Idプロパティでグループ化しています。私がむしろ持っているのはこれです:

var query = this._defaultContext.Captures
                .Include(m => m.Platform)
                .GroupBy(m => m.Platform)
                .Select(m => new {
                    Platform = m.Key,
                    Count = m.Count()
                });

これは動作しません。データベース内のレコードごとに1のカウントを取得するだけです。エンティティ全体でグループ化することはわからないようです。GetHashCodeメソッドとEqualsメソッドの実装によって各プラットフォームを区別することでそれが可能になることを望んでいましたが、運がありませんでした。

誰かがこのようなシナリオに遭遇したことがありますか?それを回避する方法はありますか?または、手動で行う必要がありますか。おそらくある種のN+1クエリになるので、私はそれを嫌います。

前もって感謝します。

4

3 に答える 3

2
var query = this._defaultContext.Captures
                    .GroupBy(m => m.Platform.Id)
                    .Select(m => new {
                        Platform = m.FirstOrDefault().Platform,
                        Count = m.Count()
                    });
于 2012-10-24T20:12:00.250 に答える
1

なぜこのアプローチを取っているのかわかりません。プラットフォームとキャプチャの間に双方向ナビゲーションを実装することを検討してください(Fluent APIとの関係の構成を参照)。そうすれば、キャプチャを含めることができ、カウントが簡単になります。

public sealed class Platform
{
    public ICollection<Capture> Captures { get; set; }
    // the rest of the stuff
}

..。

var query = this._defaultContext.Platforms.Include("Captures").Select(p => new { Platform = p, CaptureCount = p.Captures.Count() });

SQLに変換すると、これは次のように表現されます。

SELECT Platform.Id, Platform.Name, COUNT(Captures.*)
FROM Platform LEFT OUTER JOIN Capture ON Capture.Platform_Id = Platform.Id
GROUP BY Platform.Id, Platform.Name
于 2012-10-24T21:03:03.843 に答える
0

GroupByEqualityComparer<T>.Default指定しない場合は、デフォルトで使用されます。次に、実装されているかどうEqualityComparer<T>.Defaultかを確認し、T実装されIEquatable<T>ている場合はそれを使用します。

したがって、答えはIEquatable<T>同様に実装することです。

public sealed class Platform : IEquatable<Platform> {

    public override bool Equals(Platform obj) {
        return this.Equals((object)obj);
    }
    // rest of your code here 
}

でも

これがSQLに翻訳できるとは思えません。代わりに、からのナビゲーションプロパティPlatformをのリストに定義するCaptures必要がある場合があります。これにより、1つのクエリでオブジェクトが得られます。

IEqualityComparerを指定するには、そのインターフェイスをクラスに実装するだけです。

public class PlatformComparer : IEqualityComparer<Platform>
{
    public bool Equals(Platform p1, Platform p2)
    {
        if(p1 == null !! p2 == null) return false;
        return p1.Id == p2.Id;
    }
    public int GetHashCode(Platform p)
    {   
        if(p==null) throw new ArgumentNullExceltion("p");
        return p.Id.GetHashCode();
    }
}

そしてあなたのでそれを使用してくださいGroupBy

.GroupBy(m => m.Platform, new PlatformComparer())
于 2012-10-24T20:10:03.100 に答える