mbu*_*bue 3 c# domain-driven-design
我已经看到了DDD域实现,其中实体在构建Equals/GetHashCode方法时依赖于主键ID.我理解为什么这是一个好主意,因为主键可能是唯一不可变的成员.但是,也有可能出现这样的情况.
考虑一个字典,保存刚才实例化的实体.主键(假设它是自动递增值,而不是"业务相关"值)尚未分配,每个实体可能为0.现在,将保存Dictionary中的实体.这意味着主键的更改导致不同的哈希码.
我的问题:如果没有与业务相关的主键可用且所有成员都是可变的,那么对于GetHashCode应使用什么模式?
先感谢您.
在这种情况下,如果已分配Id ,我只依赖于Equals和GetHashcode方法中的Id.在其他情况下,我使用引用比较相等性.这同样适用于与GetHashCode执行; 如果已分配Id,我只根据'Id'创建一个哈希码.(也就是说,如果实体不是短暂的).
下面的代码是我使用的.这有点基于Sharp架构中的实体:
public override bool Equals( object obj )
{
Entity<TId> other = obj as Entity<TId>;
if( other == null || this.GetType() != other.GetType() )
{
return false;
}
bool otherIsTransient = Equals (other.Id, default(TId));
bool thisIsTransient = Equals (this.Id, default (TId));
if( otherIsTransient && thisIsTransient )
{
return ReferenceEquals (this, other);
}
return Id.Equals (other.Id);
}
Run Code Online (Sandbox Code Playgroud)
首先,我检查两个实体是否属于同一类型.(实际上,您也可以通过实现正确的接口来创建此方法的类型化版本(IEquality<T>)当两个实体属于同一类型时,我会检查其中一个是否是瞬态的.我只是通过检查它们的Id属性来做到这一点:如果它包含默认值,则意味着它们尚未保存在数据库中.如果它们都是瞬态的,我会在它们的引用上比较两个实体.否则,我可以在它们的ID上进行比较.
我使用的GetHashCode方法确保返回的值永远不会更改:
private int? _oldHashCode;
public override int GetHashCode()
{
// Once we have a hash code we'll never change it
if( _oldHashCode.HasValue )
{
return _oldHashCode.Value;
}
bool thisIsTransient = Equals (Id, default(TId));
// When this instance is transient, we use the base GetHashCode()
// and remember it, so an instance can NEVER change its hash code.
if( thisIsTransient )
{
_oldHashCode = base.GetHashCode ();
return _oldHashCode.Value;
}
return Id.GetHashCode ();
}
Run Code Online (Sandbox Code Playgroud)