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;
    }
}

我基本上想要的是一个 LINQ 查询,当然,它由一个 EF 支持,这将使我得到按整个平台实体分组的捕获计数。我希望能够返回对每个Platform的引用,而不是它的一个属性,以及与之关联的每个Capture的计数。

我做了这个查询,效果很好:

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。看起来它不知道按整个实体分组。我希望它可以通过GetHashCodeEquals方法实现来区分每个平台,但没有运气。

有人遇到过这样的场景吗?有什么办法吗?还是我必须手动完成。我讨厌这样,因为它可能会导致某种 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

我不确定您为什么采用这种方法。考虑在 Platform 和 Capture 之间实现双向导航(请参阅使用 Fluent API 配置关系),然后您可以包含 Captures 并且计数变得简单。

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,这将在一个查询中为您提供对象。

要指定 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 回答