Identity is a very tricky topic in DDD.
There are two schools of thought when it comes to the "timing" of identity creation:
- Identity is generated at the time the instance of that entity class is created, or
- Identity is created at the time it is persisted (when it is inserted into a relational database, for example).
The second approach can lead to a lot of problems. One which you have already raised. There are some other real issues that arise when only establishing identity at the time of persistence. Consider these two core properties of a domain entity:
- Entities are distinguished by their identity. Thus, entities cannot exist without identity.
- Entities are considered equal when their identity is equal.
When creating a new instance of an entity class using the "identity on persistence" approach, you initially have NO identity, and thus violating all of the principles above. Is identity now modeled as somewhat optional in your entities? In my opinion, this approach will lead you down a very dark road.
The only way you can get around these issues effectively is to have identity generated at the time of instantiation. This will solve your problem as well. Identity will be available to you immediately.
This may be tricky for you if your database technology automatically generates IDs.
There are several ways to generate identity at time of entity instantiation.
Generate identity within the entity:
Simplistic example:
public Person : DomainEntity<Guid>
{
//..
public Person(string name)
: base(Guid.New()) // Providing a unique GUID
{
Name = name;
}
}
Client code:
// A new person with identity!
var person = new Person("Eric Evans");
This is the preferred approach, but not always possible.
You provide the identity to the entity:
Simplistic example:
public Person : DomainEntity<int>
{
//..
public Person(int identity, string name)
: base(identity) // Providing a unique GUID
{
Name = name;
}
}
Client code:
// A new person with identity!
var person = new Person(IdentityGenerator.Create(), "Eric Evans");
The IdentityGenerator
generator may interact with your database to get and reserve the "next" identity (something which is not supported in SQL Server unfortunately).
Where do you stand?
Regarding of whether you have a composite key or not, the question you need to ask is "am I able to generate or provide entity identity at the time of instantiation?"