All entities in the domain need to have identity. By inheriting from DomainEntity
, I am able to provide identity to classes.
City domain entity (stripped down for easy reading):
public class City : DomainEntity, IAggregateRoot
{
public string Name { get; private set; }
public Coordinate Coordinate { get; private set; }
public City(string name, decimal latitude, decimal longitude)
{
Name = name;
SetLocation(latitude, longitude);
}
public City(string name, decimal latitude, decimal longitude, int id)
: base(id)
{
Name = name;
Coordinate = coordinate;
SetLocation(latitude, longitude);
}
public void SetLocation(decimal latitude, decimal longitude)
{
Coordinate = new Coordinate(latitude, longitude);
}
}
DomainEntity abstract class:
public abstract class DomainEntity
{
private int? uniqueId;
public int Id
{
get
{
return uniqueId.Value;
}
}
public DomainEntity()
{ }
public DomainEntity(int id)
{
uniqueId = id;
}
}
When a new entity is first created, an identity does not exist. Identity will only exist once the entity is persisted. Because of this, when creating a new instance of the entity, Id
does not need to be supplied:
var city = new City("Cape Town", 18.42, -33.92);
When cities are read from persistence using a CityRepository
, then the second constructor will be used so to populate the identity property as well:
public class CityRepository : ICityRepository
{
public City Find(int id)
{
var cityTblEntity = context.Set<CityTbl>().Find(id);
return new City(cityTblEntity.Name, cityTblEntity.Lat, cityTblEntity.Long, cityTblEntity.Id);
}
}
The problem I am having here is that I provide a constructor which can take in identity. This opens up a hole. I only want identity to be set in the repository layer, but client code could now also start setting Id
values. What's stopping someone from doing this:
var city = new City("Cape Town", 18.42, -33.92, 99999); // What is 99999? It could even be an existing entity!
How can I provide ways to set entity identity in my repository but to hide that from client code? Perhaps my design is flawed. Could I use factories to solve this?
Note: I understand that this is not a perfect implementation of DDD as entities should have identity from the beginning. The Guid
type would help me solve this problem, but I don't have that luxury unfortunately.