这一节我们主要和领域层打交道。首先我们要对ABP的体系结构以及从模板创建的解决方案进行一一对应。网上有代码生成器去简化我们这一步的任务,但是不建议初学者去使用。
一、首先来看看ABP体系结构
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
来实现这种通用功能。代码如下:
namespace LearningMpaAbp.Tasks
{
public class Task : Entity, IHasCreationTime
{
public const int MaxTitleLength = 256;
public const int MaxDescriptionLength = 64 * 1024;//64kb
public long? AssignedPersonId { get; set; }
[ForeignKey("AssignedPersonId")]
public User AssignedPerson { 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 = Clock.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类,添加以下代码
//TODO: Define an IDbSet for your Entities...
public IDbSet<Task> Tasks { get; set; }
4.执行Code First数据迁移。
- 打开程序包管理器控制台,默认项目选择Entityframework对应的项目后。执行
Add-Migration Add_Task_Entity
,创建迁移。 - 创建成功后,会在Migrations文件夹下创建
时间_Add_Task_Entity
格式的类文件。如果注意观察,我们会发现Migrations文件夹下有个SeedData文件夹,顾名思义,这个文件夹下的类主要是用来进行预置种子数据的。我们可以参照已有类的写法,来预置两条Task。创建DefaultTestDataForTask
类,代码如下:
namespace LearningMpaAbp.Migrations.SeedData
{
public class DefaultTestDataForTask
{
private readonly LearningMpaAbpDbContext _context;
private static readonly List<Task> _tasks;
public DefaultTestDataForTask(LearningMpaAbpDbContext 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)
{
if (_context.Tasks.FirstOrDefault(t => t.Title == task.Title) == null)
{
_context.Tasks.Add(task);
}
_context.SaveChanges();
}
}
}
}
然后在Configuration
类中的Seed
方法中,添加以下代码。
new DefaultTestDataForTask(context).Create();
- 在程序包管理器控制台,输入
Update-Database
,回车执行迁移。执行成功后,查看数据库,Tasks表创建成功,且表中已存在两条测试数据。
至此,Task实体类成功创建。
源码已上传至Github-LearningMpaAbp,可自行参考。
网友评论
但这里木有
书主可以出来 说说吗?
A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified)
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
Applying explicit migrations: [201703100356544_Add_Task_Entity].
Applying explicit migration: 201703100356544_Add_Task_Entity.
System.Data.SqlClient.SqlException (0x80131904): 找不到对象 "dbo.Tasks",因为它不存在或者您没有所需的权限。
请问下出现这个错误是什么原因?