文档目录

本节内容:

实体是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属性,它是这个实体的主键。所以所有的实体主键名都相同,都是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或其它类型。

Entity类重写了equality操作符(==),用它可以非常容易地检查两个实体是否相等(它们的Id是否相等),同时也定义了IsTransient()方法检查实体是否有一个Id。

聚合根类

“聚合在DDD里是一个模式,一个DDD聚合是一个领域对象群,可由单独的单元创建。例如一个订单和它的项,这些可以是分离的对象,但把订单(和它的项一起)看成是一个单独的聚合是有好处的。“(Martin Fowler 查看完整描述)。

虽然ABP没有强迫你使用聚合,但你也可能想在你的应用里,创建聚合和聚合根。ABP扩展了Entity,定义了AggregateRoot类,为一个聚合创建聚合根实体。

领域事件

AggregateRoot定义了DomainEvents集合,通过聚合根对象产生领域事件。这些事件在当前工作单元完成前自动触发,实质上,任何实体都可以通过实现IGeneratesDomainEvents接口产生领域事件,但通常(最佳实践)在聚合根里产生领域事件,这就是为什么把它默认到AggregateRoot里,而不是Entity类里。

约定的接口

在很多应用里,有很多相似的实体属性(数据库表的字段),如表示实体何时创建的CreationTime,ABP提供了一些有用的接口,明确和展现这些通用属性,这也给实现这些接口的实体,在编写这些属性代码时提供了一种通用的方式。

审计

IHasCreationTime为一个实体的“创建时间”信息采用通用的属性,在一个实体插入到数据库前,ABP自动为实现了该接口的实体,设置CreationTime属性为当前时间。

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

Person类改写成实现IHasCreationTime接口,如下所示:

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

ICreationAudited通过添加CreatorUserId扩展了IhasCreationTime:

public interface ICreationAudited : IHasCreationTime
{
long? CreatorUserId { 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。AuditiedEntity类同样也有一个适用于不同类型Id属性的泛型版本。

注意:ABP从ABP会话里获取用户Id。

软删除

软删除是一个通用的模式,它把一个实体标记为“已删除”代替从数据库直接删除。例如,你不想把一个User从数据库硬删除,因为它可能与其它表有关联,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; }
}

更快捷的方式是:你可以从已经实现了所有的FullAuditedEntity类继承你的实体。

  • 注意1:所有审计接口和类都有一个为指向你的User实体的导航属性而设计的泛型版本(如ICreationAudited<TUser>和FullAuditedEntity<TPrimaryKey,TUser>)。
  • 注意2:同时,它们都有一个AggregateRoot版本,如AuditedAggregateRoot。

活跃/消极 实体

有些实体需要标记为Active(活跃的)和Passive(消极的),然后你根据实体的活跃/消极状态进行不同的操作,IPassivable就是为此而设计的,它定义了IsActive属性。

如果你的实体想在创建时就是处于活跃状态,你可以在构造器里设置IsActive为true。

它与软删除(IsDeleted)不同,如果一个实体被软删除,Abp默认不从数据库里取出,但是是否获取活跃/消极实体完全取决于你。

实体变化事件

当一个实体插入、更新、删除时,ABP会自动触发某些事件,因此你可以注册这些事件执行你需要的任何逻辑。查看事件总线文档的“预定义事件”主题,获取更多信息。

IEntity 接口

实质上,Entity类实现了IEntity接口(且Entity<TPrimaryKey>实现了IEntity<TPrimaryKey>)。如果你不想从Entity类继承,你可以直接实现这些接口,这些接口对于其它实体类也是适用的,但是这不是推荐的方式,除非你有一个好的理由。

ABP框架 - 实体的更多相关文章

  1. ABP入门系列(1)——学习Abp框架之实操演练

    作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...

  2. 一步一步使用ABP框架搭建正式项目系列教程

    研究ABP框架好多天了,第一次看到这个框架的名称到现在已经很久了,但由于当时内功有限,看不太懂,所以就只是大概记住了ABP这个名字.最近几天,看到了园友@阳光铭睿的系列ABP教程,又点燃了我内心要研究 ...

  3. C#高级知识点&(ABP框架理论学习高级篇)——白金版

    前言摘要 很早以前就有要写ABP高级系列教程的计划了,但是迟迟到现在这个高级理论系列才和大家见面.其实这篇博客很早就着手写了,只是楼主一直写写停停.看看下图,就知道这篇博客的生产日期了,谁知它的出厂日 ...

  4. 一步一步使用ABP框架搭建正式项目系列教程之本地化详解

    返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 本篇目录 扯扯本地化 ABP中的本地化 小结 扯扯本地化 本节来说说本地化,也有叫国际化.全球化的,不管怎么个叫法,反正道理都是一 ...

  5. ABP框架搭建项目系列教程基础版完结篇

    返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 经过前面十二篇的基础教程,现在终于该做个总结了. 回顾 第一篇,我们建议新手朋友们先通过ABP官网的启动模板生成解决方案,因为这样 ...

  6. 详解ABP框架的多租户

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:ABP框架对多租户场景提供了很好的支持,内建了多租户的处理机制,今天我们来深入解析一下 ...

  7. [译]ABP框架使用AngularJs,ASP.NET MVC,Web API和EntityFramework构建N层架构的SPA应用程序

    本文转自:http://www.skcode.cn/archives/281 本文演示ABP框架如何使用AngularJs,ASP.NET MVC,Web API 和EntityFramework构建 ...

  8. ABP框架详解(三)Domain

    此处的Domain主要指Abp类库根目录下Domain文件夹.顾名思义该目录下是用来存放与领域实体,领域逻辑执行,存储,领域服务相关的内容. 1.Entities (1)为整个Abp框架后期开发的所有 ...

  9. AutoMapper在ABP框架中的使用说明

    为了说明AutoMapper如何使用,我专门开设了一个专题来讲,如果您还没有查看该专题,请点击这里.既然系统地学习了AutoMapper,那么接下来就是该用它实战的时候了.今天,我们就来揭开AutoM ...

随机推荐

  1. 【Machine Learning】KNN算法虹膜图片识别

    K-近邻算法虹膜图片识别实战 作者:白宁超 2017年1月3日18:26:33 摘要:随着机器学习和深度学习的热潮,各种图书层出不穷.然而多数是基础理论知识介绍,缺乏实现的深入理解.本系列文章是作者结 ...

  2. python之路 - 基础1

    1.安装windows安装双版本Python2,Python3 下载Python2和Python3https://www.python.org/downloads/ 分别安装两个版本 进入Python ...

  3. LeetCode 7. Reverse Integer

    Reverse digits of an integer. Example1: x = 123, return 321 Example2: x = -123, return -321 Have you ...

  4. Android—Volley:接收服务端发送的json数据乱码问题解决

    new JsonObjectRequest中重写方法parseNetworkResponse,内容如下: /** * 重写此方法不会导致乱码 */ @Override protected Respon ...

  5. .NET Core性能测试组件BenchmarkDotNet 支持.NET Framework Mono

    .NET Core 超强性能测试组件BenchmarkDotNet 支持Full .NET Framework, .NET Core (RTM), Mono. BenchmarkDotNet支持 C# ...

  6. 2015微软MVP全球峰会见闻

    2015.10.31-2015.11.8 一周的时间完成微软MVP全球峰会旅程,这一周在不断的倒时差,行程安排非常的紧张,还好和大家请假了没有更新微信公众号,今天开始继续更新微信公众号,开始新的旅程, ...

  7. Cowboy 开源 WebSocket 网络库

    Cowboy.WebSockets 是一个托管在 GitHub 上的基于 .NET/C# 实现的开源 WebSocket 网络库,其完整的实现了 RFC 6455 (The WebSocket Pro ...

  8. Linux Socket 网络编程

    Linux下的网络编程指的是socket套接字编程,入门比较简单.在学校里学过一些皮毛,平时就是自学玩,没有见识过真正的socket编程大程序,比较遗憾.总感觉每次看的时候都有收获,但是每次看完了之后 ...

  9. 浅谈C#网络编程(一)

    阅读目录: 基础 Socket编程 多线程并发 阻塞式同步IO 基础 在现今软件开发中,网络编程是非常重要的一部分,本文简要介绍下网络编程的概念和实践. Socket是一种网络编程接口,它是对传输层T ...

  10. .NET中使用Redis (二)

    很久以前写了一篇文章 .NET中使用Redis 介绍了如何安装Redis服务端,以及如何在.NET中调用Redis读取数据.本文简单介绍如何设计NoSQL数据库,以及如何使用Redis来存储对象. 和 ...