美文网首页ABP
ABP入门系列(2)——领域层创建实体

ABP入门系列(2)——领域层创建实体

作者: 圣杰 | 来源:发表于2017-01-07 14:27 被阅读16148次

    ABP入门系列目录——学习Abp框架之实操演练
    源码路径:Github-LearningMpaAbp


    这一节我们主要和领域层打交道。首先我们要对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,可自行参考。

    相关文章

      网友评论

      • f22843f0ec91:没有找到User这个实体
      • 0c124a828cc3:实体最好不要命名为Task,跟System.Threading.Tasks.Task重名了,后面会需要同时用到这2个对象,
        圣杰:@bones_be41 嗯,发现了就好
      • 高尔呼司机:我用的dotnet core的模板,在生成seed数据的时候,没有configuration这个类了,变成在InitialHostDbBuilder 类中进行初始化seed数据了
        48bcba9a559a:Seed文件夹下有个SeedHelper类。static SeedHostDb里面创建了InitialHostDbBuilder。所以在这里应该也是可以的
        圣杰:@高尔呼司机 灵活运用
      • 92cdab66c538:其它入门教程在此还会写一个 person实体, 毕竟task要分配到person才有完整意义
        但这里木有
        书主可以出来 说说吗?
        圣杰:@vban512 我是直接分配到user的
      • 1f6d96b02115:使用IHasCreationTime后,在构造函数里不添加creationtime的赋值也能够自动写入数据库,
      • 1f6d96b02115:IDbSet 需要自己定义么?我怎么找不到呀?
      • 76c09ccf07b8:答主。创建Tasks文件夹,并创建Task实体类应该是要创建在基础设施层(EntityFramework结尾的)
        圣杰: @匆匆过客行匆匆 实体属于领域层
      • JaniceMan玉姐:非常有收藏,感谢啦
      • 76e2d2197a86:Demo 站报错了
        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)
        圣杰:@FH_7910 试用的微软云不太稳定。现在已经ok了!
      • ZhanghaoMars:PM> Update-Database
        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",因为它不存在或者您没有所需的权限。

        请问下出现这个错误是什么原因?
        ZhanghaoMars:@圣杰 我把整个项目重新在官网下载 按照文章的步骤操作才可以 不知道原来那个问题到底出在哪里!
        圣杰: @ZhanghaoMars 仔细检查下是不是漏掉某一步。看DBContext类中有无维护DBset<Task>

      本文标题:ABP入门系列(2)——领域层创建实体

      本文链接:https://www.haomeiwen.com/subject/neojvttx.html