实体是DDD(领域驱动设计)的核心概念之一。Eric Evans 是这样描述的“很多对象不是通过它们的属性定义的,而是通过一连串的连续性事件和标识定义的”(引用领域驱动设计一书)。
注:对象不是通过它们的属性来下根本性的定义,而应该是通过它的线性连续性和标识性定义的。所以,实体是具有唯一标识的ID且存储在数据库中。实体通常被映射成数据库中的一个表。
实体类
在ABP中,实体继承自Entity类
public class Person : Entity
{
public virtual string Name { get; set; }
public virtual DateTime CreationTime { get; set; }
public Person()
{
CreationTime = DateTime.Now;
}
}
实体类Person 父类Entity具有主键属性Id。所有继承Entity类的子类都将具有主键为Id的属性。
Id的数据类型可以被更改,默认是 int类型。下面示例展示给 Id 定义其它类型。
public class Person : Entity<long>
{
public virtual string Name { get; set; }
public virtual DateTime CreationTime { get; set; }
public Person()
{
CreationTime = DateTime.Now;
}
}
可以设置为Id定义 strin,Guid 或者其它你想要的数据类型。 实体类重写了 equality (==) 操作符用来判断两个实体对象是否相等(主要是判断 Id主键 是否相等),以及 IsTransient()方法来检测当前 Id 的值是否与指定的类型的缺省值相等。
聚合根
在领域驱动设计中聚合是一种模式,聚合表示的是一组领域对象(实体和值对象),可被看作是一个单元。例:订单和订单项,这都是单独的对象。可将订单(以及订单项)作为一个聚合来看待。
ABP不强迫使用聚合,可以在你的应用中创建聚合以及聚合根。ABP定义扩展自 Entity 的 AggregateRoot 类,用来创建聚合根实体。
领域事件
聚合根定义 DomainEvents 的集合来产生领域事件。在当前的工作单元完成之前,这些事件被自动的触发。通过扩展 IGeneratesDomainEvents 接口,任何实体都能够产生领域事件。但是,最佳实践是在聚合根中产生领域事件。这就是为什么它被定义在聚合根中而不是实体中。
实体更改事件
当实体被插入,更新或者删除的时候,ABP会自动的触发相应的事件。因此,你可以注册这些事件并执行任何你需要的逻辑。
Entity 实现 IEntity 接口(Entity IEntity接口)。如果你不想从 Entity 类派生,你能直接的实现IEntity 接口。其他实体类也可以实现相应的接口。但是不建议你用这种方式。除非你有一个很好的理由不从 Entity 类派生。