【问题标题】:Is there a sample why Equals/GetHashCode should be overwritten in NHibernate?是否有一个示例为什么 Equals/GetHashCode 应该在 NHibernate 中被覆盖?
【发布时间】:2012-07-11 20:49:43
【问题描述】:

我发现很多帖子都解释说应该始终覆盖 NHibernate 实体类上的 Equals/GetHashCode。如果我不使用 Sets,这真的有必要吗?

我根本找不到一个示例,它表明缺少 Equals/GetHashCode 会导致意外和错误的行为。 没有它们,一切似乎都可以正常工作。这真的很奇怪,每个人都说这是必要的,但没有人能提供一个示例来说明为什么这是必要的。

【问题讨论】:

    标签: c# .net nhibernate domain-driven-design


    【解决方案1】:

    事实上,只有极少数情况会导致副作用。但如果你得到它们,它们就会非常微妙。除了复合主键和字典键,它们总是需要正确的 Equals / GetHashCode 实现。

    NH 只关心在内存中实例化一个实体一次,所以默认的引用比较应该可以工作......如果没有延迟加载

    如果不覆盖 Equals,则在处理代理时会遇到问题。总是有两个实例:代理和真实实体。它们都代表同一个实体。只有使用正确实现的 Equals 方法,它才会被视为相同。

    【讨论】:

    • 好的,所以这意味着如果我不使用复合键或字典,唯一的原因是使实体及其代理的使用透明。
    • 我知道的唯一原因。我们在项目中没有实现 Equals / GetHashCode 也没有遇到任何问题,直到我们开始使用延迟加载。
    • 我在this post 中添加了一个示例,它显示了相等性如何简单地失败。如果您有一个与延迟加载集合进行比较的对象,您将遇到将代理与真实实体进行比较的情况(默认引用相等将失败!)。 IMO,不应该“只在这些边缘情况下做”,在调试这些问题时,您应该始终这样做以保持理智。
    【解决方案2】:

    最近在 SO 上有一个question,关于 NHibernate 执行选择 N+1,即使指定了 fetch。问题was 缺少Equals / GetHashCode 实现。

    答案链接到另一个类似的question

    这里是 another question 关于 Equals / GetHashCode 覆盖背后的推理。

    Nhibernate n+1 with ternary relationship. Want the middle entity in the ternary
    Nhibernate producing proxy despite HQL fetch
    NHibernate: Reasons for overriding Equals and GetHashCode
    Why Equals and GetHashCode are so important to NHibernate
    Why is it important to override GetHashCode when Equals method is overridden?


    编辑

    您不需要一直覆盖它们。如果您使用复合键、具有分离实体的多个会话或无状态会话,则可能有必要。

    如果您只使用单个会话,NHibernate 将使用身份映射将实体存储到第一级缓存。在这种情况下,实体比较是通过比较 id 来完成的。

    在上述情况下(分离实体、无状态会话),NHibernate 比较实际实体,而不是它们的 ID。默认情况下,Object.Equals 确实引用相等。因此,如果两个对象指向完全相同的实例,则它们是相等的。您可能有两个具有相同标识的实例,但 Object.Equals 会为它们返回 false。这与Entity definition 形成对比:

    不是由其属性定义的对象,而是由 连续性的线程及其身份。

    JBoss Hibernate wiki 在EqualsHashCode 上有a good explanation,几乎没有代码示例。

    【讨论】:

    • 这似乎只与复合键有关。我们不使用它们。那么这是唯一需要 Equals/GetHashCOde 的情况吗?我知道你链接的最后三个链接。我没有看到任何重现错误行为的代码示例。
    • 复合 ID 是一种情况。我已经用一些文本和指向 Hibernate 的 wiki 页面的链接更新了我的答案...
    • -1 比较代理和真实对象will cause problems。除非您覆盖Equals,否则始终使用引用相等。您应该始终覆盖 Equals/GetHashCode 并使用身份比较。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多