一、首先来看看ABP体系结构
领域层就是业务层,是一个项目的核心,所有业务规则都应该在领域层实现。
实体(Entity): 实体代表业务领域的数据和操作,在实践中,通过用来映射成数据库表。
仓储(Repository): 仓储用来操作数据库进行数据存取。仓储接口在领域层定义,而仓储的实现类应该写在基础设施层。
领域服务(Domain service): 当处理的业务规则跨越两个(及以上)实体时,应该写在领域服务方法里面。
领域事件(Domain Event): 在领域层有些特定情况发生时可以触发领域事件,并且在相应地方捕获并处理它们。
工作单元(Unit of Work): 工作单元是一种设计模式,用于维护一个由已经被修改(如增加、删除和更新等)的业务对象组成的列表。它负责协调这些业务对象的持久化工作及并发问题。
二、再来看看解决方案
确定了解决方案下每个项目分别对应那一层后,我们开始创建Task实体。
三、创建Task实体
1.在领域层创建Tasks文件夹,并创建Task实体类;
2.ABP中所有的实体类都继承自Entity
,而Entity
实现了IEntity
接口;而IEntity
接口是一个泛型接口,通过泛型指定主键Id类型,默认的Entity
的主键类型是int类型。创建Task,肯定需要保存创建时间,可以通过实现审计模块中的IHasCreationTime
来实现这种通用功能。代码如下:
using Abp.Domain.Entities; using Abp.Domain.Entities.Auditing; using MyProject.Authorization.Users; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyProject.Tasks { public class Task : Entity, IHasCreationTime { public const int MaxTitleLength = 256; public const int MaxDescriptionLength = 64 * 1024; public long? AssignePersonId { get; set; } [ForeignKey("AssignePersonId")] public User AssignePerson { get; set; } [Required] [MaxLength(MaxTitleLength)] public string Title { get; set; } [Required] [MaxLength(MaxDescriptionLength)] public string Description { get; set; } public TaskState State { get; set; } public DateTime CreationTime { get; set; } public Task() { CreationTime = DateTime .Now; State = TaskState.Open; ; } public Task(string title, string description = null) : this() { Title = title; Description = description; } } public enum TaskState : byte { Open = 0, Completed = 1 } }
其中定义了TaskState
状态枚举。并添加了AssignedPerson
导航属性,用来保存分配任务到某个用户。其中[Required]、[MaxLength]特性是用来进行输入校验的。
3.定义好实体之后,我们就要去DbContext
中定义实体对应的DbSet
,以应用Code First 数据迁移。找到我们的基础服务层,即以EntityFramework结尾的项目中,找到DbContext类,添加以下代码
4.执行Code First数据迁移。
- 打开程序包管理器控制台,默认项目选择Entityframework对应的项目后。执行
Add-Migration Add_Task_Entity
,创建迁移。 - 创建成功后,会在Migrations文件夹下创建
时间_Add_Task_Entity
格式的类文件。如果注意观察,我们会发现Migrations文件夹下有个SeedData文件夹,顾名思义,这个文件夹下的类主要是用来进行预置种子数据的。我们可以参照已有类的写法,来预置两条Task。创建DefaultTestDataForTask
类,代码如下: -
using System; using System.Collections.Generic; using System.Linq; using System.Text; using MyProject.EntityFramework; using MyProject.MultiTenancy; using MyProject.Tasks; namespace MyProject.Migrations.SeedData { public class DefaultTestDataForTask { private readonly MyProjectDbContext _context; private static readonly List<Task> _tasks; public DefaultTestDataForTask(MyProjectDbContext context) { _context = context; } static DefaultTestDataForTask() { _tasks = new List<Task>() { new Task("Learning ABP deom","Learning how to use abp framework to build a MPA application."), new Task ("Make Lunch","Cook 2 dishs") }; } public void Create() { foreach (var task in _tasks) { _context.Tasks.Add(task); _context.SaveChanges(); } } } }
然后在Configuration
类中的Seed
方法中,添加以下代码。
- 在程序包管理器控制台,输入
Update-Database
,回车执行迁移。执行成功后,查看数据库,Tasks表创建成功,且表中已存在两条测试数据。
至此,Task实体类成功创建。