【发布时间】:2014-02-10 14:33:24
【问题描述】:
在领域驱动设计中,实体的定义特征之一是它具有身份。
问题:
我无法在创建实例时向实体提供唯一身份。此身份仅在实体持久化后由存储库提供(此值由底层数据库提供)。
此时我无法开始使用Guid 值。现有数据与int 主键值一起存储,我无法在实例化时生成唯一的 int。
我的解决方案:
- 每个实体都有一个标识值
- 身份只有在持久化后才设置为真实身份(由数据库提供)
- 在持久化之前实例化时标识设置为默认值
- 如果标识为默认值,则实体可通过引用进行比较
- 如果标识不是默认值,实体可通过标识值进行比较
代码(所有实体的抽象基类):
public abstract class Entity<IdType>
{
private readonly IdType uniqueId;
public IdType Id
{
get
{
return uniqueId;
}
}
public Entity()
{
uniqueId = default(IdType);
}
public Entity(IdType id)
{
if (object.Equals(id, default(IdType)))
{
throw new ArgumentException("The Id of a Domain Model cannot be the default value");
}
uniqueId = id;
}
public override bool Equals(object obj)
{
if (uniqueId.Equals(default(IdType)))
{
var entity = obj as Entity<IdType>;
if (entity != null)
{
return uniqueId.Equals(entity.Id);
}
}
return base.Equals(obj);
}
public override int GetHashCode()
{
return uniqueId.GetHashCode();
}
}
问题:
- 您是否认为这是在创建实例时生成 Guid 值的好方法?
- 对于这个问题有更好的解决方案吗?
【问题讨论】:
-
您使用的是什么数据库?如果您使用的是 RavenDB 或 NHibernate,您也许可以利用 HiLo 模式,它允许您在将实体持久保存到数据库之前提前获取 id。
-
基于 Azure SQL 数据库的实体框架 6。我不相信在插入东西之前有可能得到一个 id。
-
为什么在实体被持久化之前需要一个 id 以及为什么你必须依赖数据库提供的值?请向我们提供有关您的域的更多详细信息,因为您的假设可能是错误的。
-
@BartłomiejSzypelow:因为实体需要有身份,有时甚至从实例化的角度来看也是如此。我可以只依赖参考,但我正在开发一个分布式系统,因此实体的身份需要由 Id 限定(因为会发生序列化)。我正在尝试实现早期身份生成(查看 Vaughn Vernon 的书:实施领域驱动设计)。
-
您提到了分布式。 GUID 的另一个原因。正如您提到的 IDDD,还有一章是关于使用模仿 Oracle 的 SEQUENCE 的表进行早期身份生成的黑客攻击。我不喜欢这种方法,但你呢?
标签: c# domain-driven-design repository-pattern domain-model aggregateroot