Nhibernate 在比较值对象的相等性时如何处理null?

Nhibernate 在比较值对象的相等性时如何处理null?,nhibernate,null,domain-driven-design,equals,value-objects,Nhibernate,Null,Domain Driven Design,Equals,Value Objects,注意:我以C为例,但在Java和许多其他语言中,问题实际上是相同的 假设您实现了如中所示的值对象,并且它有一些可为空的字段: class MyValueObject { // Nullable field (with public access to keep the example short): public string MyField; } 然后,当重写Equals时,如何处理两个值对象的MyField都设置为null的情况?他们是否平等 在C中,将他们视为平等似

注意:我以C为例,但在Java和许多其他语言中,问题实际上是相同的

假设您实现了如中所示的值对象,并且它有一些可为空的字段:

class MyValueObject
{   
    // Nullable field (with public access to keep the example short):
    public string MyField;
}
然后,当重写Equals时,如何处理两个值对象的MyField都设置为null的情况?他们是否平等

在C中,将他们视为平等似乎是显而易见的,因为:

当您使用C结构而不是类并且不重写Equals时,这是Equals的行为

以下表达式是正确的:

null == null
object.ReferenceEquals(null, null)
object.Equals(null, null)
但是,在SQL中,至少在SQL Server的方言中,NULL=NULL为false,而NULL为NULL为true

我想知道在我的例子中使用O/R映射器时,需要什么样的实现,NHibernate。如果您实现了自然的C相等语义,当O/R映射器将它们映射到数据库时,可能会有任何不良影响吗


或者在值对象中允许可为null的字段是错误的?

我个人认为,如果在无错误代码中可以为null,那么它们应该被视为相等的。 然而,如果它不应该是空的:客户的名字,或者送货的街道地址,那么它一开始就不应该是空的。

因为ORM知道关系模型,所以它们通常公开一种使用SQL语义进行查询的方法

例如,NHibernate在HQL中提供is[not]null运算符,并在条件中提供Restrictions.is[not]null


当然,有一个API使这些范例发生冲突:LINQ。大多数ORM在与null进行比较时会尝试做正确的事情,即替换为is null,尽管有时会出现问题,尤其是在行为不明显的情况下。

我认为您有两个问题:

一个是您需要知道MyValueObject的一个实例是否等于另一个实例

第二,这应该如何转化为持久性

我认为您需要单独查看这些,因为您的角度似乎将它们耦合得太近,这在我看来似乎违反了一些DDD原则-域不应该知道/关心持久性

如果您不确定MyField的null值的效果,请让它返回字符串以外的其他类型;b让它返回一个类似字符串的派生字符串或类似的实现;c或重写Equals方法,并精确指定这些实例相等的含义

如果您的ORM无法将涉及MyValueObject的特定表达式转换为SQL,那么也许可以在持久性层中进行更艰苦的工作,并在SQL转换过程中进行比较-是的,我知道性能问题,但我确信,为了保持域模型干净,并非不可能解决。似乎解决方案应该从对我来说最适合的领域模型中派生出来


@詹姆斯·安德森提出了一个很好的观点。为错误和故障状态保留null。我认为这似乎越来越合适。

上帝帮助我理解为什么SQL强制人们使用is null表示等于null,而不是使用perfectly good=运算符。在C和大多数其他语言中,如果两个字段都为null,则对象是相等的。还有SQL!他们只是强迫您使用is而不是=我认为SQL NULL相等行为的思想是NULL可以是任何东西。它没有明确定义的真实世界语义。因此,一个空值实际上可能是缺少的“foo”,而另一个空值可能是缺少的“bar”。然后,当比较时,SQL不能知道两个空值是否相等,并且表现为保守,这使得它不认为空值是相等的。也不认为他们是不平等的!空!=null也是false。另一方面,在C中,null只是一个空的/缺少的引用。@Kirk,因为根据定义,任何对null的压缩都是假的。在实代数中,空表示你不知道。所以,如果我不知道我会在哪一天死去,而你也不知道你会在哪一天死去,这并不意味着我们都会在同一天死去。