原文作者:圣杰
原文地址:ABP入门系列(2)——领域层创建实体
在原文作者上进行改正,适配ABP新版本。内容相同
这一节我们主要和领域层打交道。首先我们要对ABP的体系结构以及从模板创建的解决方案进行一一对应。网上有代码生成器去简化我们这一步的任务,但是不建议初学者去使用。
一、首先来看看ABP体系结构
领域层就是业务层,是一个项目的核心,所有业务规则都应该在领域层实现。
实体(Entity): 实体代表业务领域的数据和操作,在实践中,通过用来映射成数据库表。
仓储(Repository): 仓储用来操作数据库进行数据存取。仓储接口在领域层定义,而仓储的实现类应该写在基础设施层。
领域服务(Domain service): 当处理的业务规则跨越两个(及以上)实体时,应该写在领域服务方法里面。
领域事件(Domain Event): 在领域层有些特定情况发生时可以触发领域事件,并且在相应地方捕获并处理它们。
工作单元(Unit of Work): 工作单元是一种设计模式,用于维护一个由已经被修改(如增加、删除和更新等)的业务对象组成的列表。它负责协调这些业务对象的持久化工作及并发问题。
实体(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
来实现这种通用功能。代码如下:
1 using Abp.Domain.Entities; 2 using Abp.Domain.Entities.Auditing; 3 using Abp.Timing; 4 using Coreqi.Authorization.Users; 5 using System; 6 using System.Collections.Generic; 7 using System.ComponentModel.DataAnnotations; 8 using System.ComponentModel.DataAnnotations.Schema; 9 using System.Text; 10 11 namespace Coreqi.Tasks 12 { 13 public class Task : Entity, IHasCreationTime 14 { 15 public const int MaxTitleLength = 256; 16 public const int MaxDescriptionLength = 64 * 1024; 17 public long? AssignedPersonId { get; set; } 18 [ForeignKey("AssignedPersonId")] 19 public User AssignedPerson { get; set; } 20 21 [Required] 22 [MaxLength(MaxTitleLength)] 23 public string Title { get; set; } 24 25 [Required] 26 [MaxLength(MaxDescriptionLength)] 27 public string Description { get; set; } 28 29 public TaskState State { get; set; } 30 31 public DateTime CreationTime { get; set; } 32 33 public Task() 34 { 35 CreationTime = Clock.Now; 36 State = TaskState.Open; 37 } 38 public Task(string title ,string description = null): this() 39 { 40 Title = title; 41 Description = description; 42 } 43 } 44 public enum TaskState : byte 45 { 46 Open = 0, 47 Completed = 1 48 } 49 }
其中定义了TaskState
状态枚举。并添加了AssignedPerson
导航属性,用来保存分配任务到某个用户。其中[Required]、[MaxLength]特性是用来进行输入校验的。
3.定义好实体之后,我们就要去DbContext
中定义实体对应的DbSet
,以应用Code First 数据迁移。找到我们的基础服务层,即以EntityFramework结尾的项目中,找到DbContext类,添加以下代码
1 using Microsoft.EntityFrameworkCore; 2 using Abp.Zero.EntityFrameworkCore; 3 using Coreqi.Authorization.Roles; 4 using Coreqi.Authorization.Users; 5 using Coreqi.MultiTenancy; 6 using Coreqi.Tasks; 7 8 namespace Coreqi.EntityFrameworkCore 9 { 10 public class CoreqiDbContext : AbpZeroDbContext<Tenant, Role, User, CoreqiDbContext> 11 { 12 /* Define a DbSet for each entity of the application */ 13 public DbSet<Task> Tasks { get; set; } 14 public CoreqiDbContext(DbContextOptions<CoreqiDbContext> options) 15 : base(options) 16 { 17 } 18 } 19 }
4.执行Code First数据迁移。
- 打开程序包管理器控制台,默认项目选择Entityframework对应的项目后。执行
Add-Migration Add_Task_Entity
,创建迁移。 - 创建成功后,会在Migrations文件夹下创建
时间_Add_Task_Entity
格式的类文件。 - 在EntityFrameworkCore=》Seed=》Host目录下新建DefaultTaskCreator类用于预置两条Task种子数据。
1 using Coreqi.Tasks; 2 using System; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Text; 6 7 namespace Coreqi.EntityFrameworkCore.Seed.Host 8 { 9 public class DefaultTaskCreator 10 { 11 private readonly CoreqiDbContext _context; 12 13 private static readonly List<Task> _tasks; 14 15 public DefaultTaskCreator(CoreqiDbContext context) 16 { 17 _context = context; 18 } 19 20 static DefaultTaskCreator() 21 { 22 _tasks = new List<Task>() 23 { 24 new Task("Learning ABP deom", "Learning how to use abp framework to build a MPA application."), 25 new Task("Make Lunch", "Cook 2 dishs") 26 }; 27 } 28 29 public void Create() 30 { 31 CreateTasks(); 32 } 33 34 private void CreateTasks() 35 { 36 foreach (var task in _tasks) 37 { 38 if (_context.Tasks.FirstOrDefault(t => t.Title == task.Title) == null) 39 { 40 _context.Tasks.Add(task); 41 } 42 _context.SaveChanges(); 43 } 44 } 45 } 46 }
然后在InitialHostDbBuilder类中的Create方法中,添加以下代码。
1 public void Create() 2 { 3 new DefaultEditionCreator(_context).Create(); 4 new DefaultLanguagesCreator(_context).Create(); 5 new HostRoleAndUserCreator(_context).Create(); 6 new DefaultSettingsCreator(_context).Create(); 7 8 //add 9 new DefaultTaskCreator(_context).Create(); 10 11 _context.SaveChanges(); 12 }
在程序包管理器控制台,输入Update-Database
,回车执行迁移。执行成功后,运行xxxx.Web.Host项目,查看数据库,Tasks表创建成功,且表中已存在两条测试数据。
至此,Task实体类成功创建。