是否有一个示例为什么应该在NHibernate中覆盖Equals / GetHashCode?

我发现很多post都解释说应该总是在NHibernate实体类上重写Equals / GetHashCode。 如果我不使用套装,这真的有必要吗?

我根本找不到一个示例,其中显示缺少Equals / GetHashCode会导致意外和错误的行为。 没有它们,一切似乎都很完美。 这是非常奇怪的,每个人都说这是必要的,但没有人可以提供一个样本,说明为什么需要这样做。

最近SO上有一个关于NHibernate做选择N + 1的问题,即使指定了fetch也是如此。 问题是缺少Equals / GetHashCode实现。

答案链接到另一个类似的问题 。

这是关于Equals / GetHashCode覆盖背后推理的另一个问题 。

Nhibernate n + 1与三元关系。 想要三元组中的中间实体
尽管有HQL提取,Nhibernate仍会生成代理
NHibernate:重写Equals和GetHashCode的原因
为什么Equals和GetHashCode对NHibernate如此重要
为什么在重写Equals方法时重写GetHashCode很重要?


编辑

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

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

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

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

JBoss Hibernate wiki对EqualsHashCode有很好的解释 ,只有很少的代码示例。

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

NH关心在内存中只实例化一次实体,因此默认参考比较应该有效… 如果没有延迟加载

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