身份是 DDD 中一个非常棘手的话题。
关于身份创建的“时机”,有两种思想流派:
- 标识是在创建该实体类的实例时生成的,或者
- 身份是在持久化时创建的(例如,当它插入关系数据库时)。
第二种方法会导致很多问题。你已经提出的一个。当仅在持久性时建立身份时,还会出现其他一些实际问题。考虑域实体的这两个核心属性:
- 实体通过它们的身份来区分。因此,实体不能没有身份而存在。
- 当它们的身份相同时,实体被认为是平等的。
当使用“持久性身份”方法创建实体类的新实例时,您最初没有身份,因此违反了上述所有原则。身份现在在您的实体中建模为多少可选?在我看来,这种方法会带你走上一条非常黑暗的道路。
有效解决这些问题的唯一方法是在实例化时生成标识。这也将解决您的问题。身份将立即提供给您。
如果您的数据库技术自动生成 ID,这对您来说可能会很棘手。
有几种方法可以在实体实例化时生成身份。
在实体内生成身份:
简单的例子:
public Person : DomainEntity<Guid>
{
//..
public Person(string name)
: base(Guid.New()) // Providing a unique GUID
{
Name = name;
}
}
客户端代码:
// A new person with identity!
var person = new Person("Eric Evans");
这是首选方法,但并非总是可行。
您向实体提供身份:
简单的例子:
public Person : DomainEntity<int>
{
//..
public Person(int identity, string name)
: base(identity) // Providing a unique GUID
{
Name = name;
}
}
客户端代码:
// A new person with identity!
var person = new Person(IdentityGenerator.Create(), "Eric Evans");
生成器IdentityGenerator
可能会与您的数据库交互以获取和保留“下一个”标识(不幸的是,SQL Server 不支持此标识)。
你站在哪里?
关于您是否有复合键,您需要问的问题是“我是否能够在实例化时生成或提供实体身份?”