实体

  实体是DDD(领域驱动设计)的核心概念之一。Eric Evans描述它为"An object that is not fundamentally defined by its attributes, but rather by a thread of continuity and identity."所以,实体有Id并存储在数据库。实体一般映射到关系库中的表。

实体类

  在ABP,实体继承自Entity类。如下示例:

public class Person : Entity
{
public virtual string Name { get; set; } public virtual DateTime CreationTime { get; set; } public Person()
{
CreationTime = DateTime.Now;
}
}

  Persion类定义为实体。它有两个属性,实体类还定义了Id属性,它是实体的主键。所以,所有实体主键的名字都一样,为Id。

  Id(主键)的类型可以改变,默认为int(Int32)类型。如果想定义其他类型作为Id,可以按如下所示显示的声明:

public class Person : Entity<long>
{
public virtual string Name { get; set; } public virtual DateTime CreationTime { get; set; } public Person()
{
CreationTime = DateTime.Now;
}
}

  还可以将主键类型设置为String、Guid或其他类型。

  实体类重写了相等运算符(==),可以方便的检查两个实体是否相等(Id相同)。实体还定义了IsTransient()方法检查是否有Id。

聚合根类

  “在DDD中,聚合是一种模式。一个DDD聚合是领域对象群集,这些领域对象可以作为一个单元对待。例如订单和它的行项目,这些是独立的对象,但是把订单(和它的行项目)作为一个聚合对待是有用的。”(Martin Fowler -参见详细描述)。

  虽然ABP不强制使用聚合,在应用中,我们或许想创建聚合和聚合根。ABP定义了AggregateRoot类,它扩展了实体为聚合创建聚合根实体。

领域事件

  聚合根定义了领域事件集合,通过聚合根类产生领域事件。这些事件在当前工作单元完成之前自动触发。实际上,任何实体可以通过实现IGeneratesDomainEvents接口来生成领域事件,但是,通常在(最佳实践)聚合根中生成领域事件。这就是为什么默认为聚合根而不是其他实体类。

常规接口

  在许多应用中,相似的实体属性(和数据库表字段)被使用,如CreationTime表示实体什么事件被创建。ABP提供了一些有用的接口使这些常见属性显示声明。这也提供了编写实体常用代码的一种方式,实现这些接口。

审计

  IHasCreationTime使实体拥有一个常用的"creation time"属性。当实现了这个接口的实体被插入到数据库时,ABP自动设置CreationTime为当前时间。

public interface IHasCreationTime
{
DateTime CreationTime { get; set; }
}

  ABP自动设置CreatorUserId为当前用户Id,当保存一个新实体的时候。也可以通过将实体继承CreationAuditedEntity类来实现ICreationAudited接口。它也有一个泛型版本,可以实现不同类型的Id属性。

  修改也有类似的接口:

public interface IHasModificationTime
{
DateTime? LastModificationTime { get; set; }
} public interface IModificationAudited : IHasModificationTime
{
long? LastModifierUserId { get; set; }
}

  当更新实体时,ABP自动设置这些属性。只需要在实体中定义他们。

  如果想实现所有的审计属性,可以直接实现IAudited接口:

public interface IAudited : ICreationAudited, IModificationAudited
{ }

  有一个捷径,可以直接继承AuditedEntity类而不是直接实现IAudited接口。AuditedEntity类也有一个泛型版本,以适应不同类型的Id属性。

  注意:ABP从ABP会话中获取当前用户Id。

软删除

  软删除是常用的模式,用来标记实体删除而不是真的从数据库中删除。例如,可能不想从数据库中硬删除一个用户,因为它和其他表有许多关系。ISoftDelete接口用来实现这个目的:

public interface ISoftDelete
{
bool IsDeleted { get; set; }
}

  ABP实现了开箱即用的软删除模式。当软删除实体被删除时,ABP会检测到并阻止删除,设置IsDeleted为true,然后更新实体到数据库。ABP不会从数据库中获取(select)软删除的实体,自动过滤他们。

  如果使用软删除,也想记录实体什么时候被删除、谁删除,可以实现IDeletionAudited接口,如下所示:

public interface IDeletionAudited : ISoftDelete
{
long? DeleterUserId { get; set; } DateTime? DeletionTime { get; set; }
}

  IDeletionAudited扩展了ISoftDelete接口。当实体被删除时,ABP自动记录这些属性。

  如果想让实体实现所有的审计接口(creation、modification和deletion),可以直接实现IFullAudited接口,因为它继承自所有接口:

public interface IFullAudited : IAudited, IDeletionAudited
{ }

  有个捷径,可以使实体继承自FullAuditedEntity类,它实现了所有。

  • NOTE1:所有的审计接口和类都有一个泛型版本,用来定义User实体(如ICreationAudited<TUser>和FullAuditedEntity<TPrimaryKey,TUser>)的导航属性。
  • NOTE2:所有这些都有一个聚合根版本,如AuditedAggregateRoot。

激活/失活实体

  一些实体需要被记录为激活或失活。然后可以基于实体的激活/失活状态进行操作。可以实现IPassiveable接口,这个接口便是为这个目的设计的。它定义了IsActive属性。

  如果实体第一次创建时为激活状态,那么可以在构造函数中设置IsActive为true。

  这和软删除(IsDeleted)是不同的。如果实体被软删除,它不能从数据库中获取(ABP默认会阻止获取),但是,对于激活/失活的实体,控制获取实体完全由自己决定。

实体改变事件

  当实体被插入、更新或删除时,ABP自动触发这些确定的事件。然后,我们可以注册这些事件,执行需要的任何逻辑。参见在事件总线文档的预定义事件部分了解更多信息。

IEntity接口

  实际上,Entity类实现了IEntity接口(Entity<TPrimaryKey>实现了IEntity<TPrimaryKey>)。如果不想从Entity类集成,可以直接实现这些接口。其他实体类也有相关的接口。但是,不建议使用这种方式,除非有好的理由不从Entity类继承。

返回主目录

ABP官方文档翻译 3.1 实体的更多相关文章

  1. ABP官方文档翻译 3.3 仓储

     仓储 默认仓储 自定义仓储 自定义仓储接口 自定义仓储实现 基础仓储方法管理数据库连接 查询 获取单个实体 获取实体列表 关于IQueryable 自定义返回值 插入 更新 删除 其他 关于异步方法 ...

  2. ABP官方文档翻译 10.1 ABP Nuget包

    ABP Nuget包 Packages Abp Abp.AspNetCore Abp.Web.Common Abp.Web Abp.Web.Mvc Abp.Web.Api Abp.Web.Api.OD ...

  3. ABP官方文档翻译 9.3 NHibernate集成

    NHibernate集成 Nuget包 配置 实体映射 仓储 默认实现 自定义仓储 应用程序特定基础仓储类 ABP可以使用任何ORM框架,它内置集成NHibernate.此文档将讲解ABP如何使用NH ...

  4. ABP官方文档翻译 9.2 Entity Framework Core

    Entity Framework Core 介绍 DbContext 配置 在Startup类中 在模块PreInitialize方法中 仓储 默认仓储 自定义仓储 应用程序特定基础仓储类 自定义仓储 ...

  5. ABP官方文档翻译 9.1 EntityFramework集成

    EntityFramework集成 Nuget包 DbContext 仓储 默认仓储 自定义仓储 应用特定的基础仓储类 自定义仓储示例 仓储最佳实践 事务管理 数据存储 ABP可以使用ORM框架,它内 ...

  6. ABP官方文档翻译 8.1 通知系统

    通知系统 介绍 发送模型 通知类型 通知数据 通知严重性 关于通知持久化 订阅通知 发布通知 用户通知管理 实时通知 客户端 通知存储 通知定义 介绍 在系统中通知用来基于特定的事件告知用户.ABP提 ...

  7. ABP官方文档翻译 7.1 后台Jobs和Workers

    后台Jobs和Workers 介绍 后台Jobs 关于Job持久化 创建后台Job 在队列中添加一个新Job 默认的后台Job管理器 后台Job存储 配置 禁用Job执行 异常处理 Hangfire集 ...

  8. ABP官方文档翻译 5.3 OData集成

    OData集成 介绍 安装 安装Nuget包 设置模块依赖 配置实体 创建控制器 配置 示例 获取实体列表 Request Response 获取单个实体 Request Response 使用导航属 ...

  9. ABP官方文档翻译 4.2 数据传输对象

    数据传输对象 DTOs的必要性 领域层的抽象 数据隐藏 序列化和懒加载问题 DTO转换和验证 示例 DTOs和实体间的自动映射 辅助接口和类 数据传输对象用来在应用层和展示层之间传输数据. 展示层调用 ...

随机推荐

  1. AtCoder Regular Contest 078

    我好菜啊,ARC注定出不了F系列.要是出了说不定就橙了. C - Splitting Pile 题意:把序列分成左右两部分,使得两边和之差最小. #include<cstdio> #inc ...

  2. 基于Windows环境下cmd/编译器无法输入中文,显示中文乱码解决方案

    基于Windows环境下cmd/编译器无法输入中文,显示中文乱码解决方案 两个月前做C++课设的时候,电脑编译器编译结果出现了中文乱码,寻求了百度和大神们,都没有解决这个问题,百度上一堆解释是对编译器 ...

  3. Win10没有以太网图标如何找回?以太网适配器不见了怎么恢复?

    Win10以太网适配器不见了怎么恢复?以太网其实就是Win7系统中常说的"本地连接"假若用户发现网络适配器中的以太网适配器图标不见了,可以在设备管理器中添加一些这类适配器,具体过程 ...

  4. [国嵌攻略][090][linux网络编程模型]

    编程模型 Socket的实质就是一个接口,利用该接口,用户在使用不同的网络协议时,操作函数得以统一.而针对不同协议的差异性操作,则交给了Socket去自行解决. TCP编程模型 UDP编程模型

  5. jQuery中获取文档的高度、可视区域高度以及滚动条距页面顶部的高度

    在写页面的时候,经常会碰到这样的情况,就是要获取文档的高度.可视区域高度或者滚动条距页面顶部的高度等情况. 但我总是有些爱搞混淆了,这里还是简单做个笔记吧,这里只限于使用jQuery来获取. 1.获取 ...

  6. FTP下载导致Zip解压失败的原因

    情形:网关通过FTP下载快钱对账文件时通过Apache下commons-net的commons-net-3.5.jar进行封装,对账文件中有中文和英文的文字,大部分情况下能够下载成功,而且也能解压成功 ...

  7. JSP学习总结

    1. 为什么需要jsp?  Servlet对于逻辑处理是非常方便的,但是对于页面的展现是非常麻烦的.JSP的诞生是为了解决Servlet页面展现麻烦的问题的. 2. JSP的特点:     Jsp页面 ...

  8. Spark学习笔记3(IDEA编写scala代码并打包上传集群运行)

    Spark学习笔记3 IDEA编写scala代码并打包上传集群运行 我们在IDEA上的maven项目已经搭建完成了,现在可以写一个简单的spark代码并且打成jar包 上传至集群,来检验一下我们的sp ...

  9. memcached经典问题和现象

    缓存刷新时间集中问题 某个缓存失效了,导致其他节点的缓存命中率下降, 缓存中缺失的数据 去数据库查询.短时间内,会造成数据库服务器崩溃 需要将缓存失效时间离散分布在访问量比较低的时间段 multige ...

  10. Ajax 跨域,这应该是最全的解决方案了

    https://segmentfault.com/a/1190000012469713 前言 从刚接触前端开发起,跨域这个词就一直以很高的频率在身边重复出现,一直到现在,已经调试过N个跨域相关的问题了 ...