基于abp框架的数据库种子数据初始化

Abp系列

一.abp框架运行——前后端分离(基于VUE)

二.基于abp框架的数据库种子数据初始化

基于abp框架的数据库种子数据初始化

1.背景

最近在用abp开发项目,需要将如下区域数据通过程序的初次运行种入数据库。

不知道大家是怎么去管理数据库跟后台程序的同步的,基于Git的数据库sql文件的管理——完美解决团队sql操作协同问题,此文是我以前的一个思考。
但是有三个缺点:

  1. 运维总会忘记去更新数据库,导致异常;
  2. 不同的后端有时候也难以同步;
  3. 管理sql本身要耗费一定的经历。
    综上,此次开发决定数据库的初始化数据写在程序中,与程序一同管理。解决了上述三个问题。

备注本文用的abp框架为第一代,官网:https://aspnetboilerplate.com/。 模板下载运行方法(前后端分离)可以参照此文abp框架运行——前后端分离(基于VUE)

2.参照

本文执行方法参照的是abp框架的默认语言种子数据种入。

3.解决方案

3.1 初始化数据

    //初始化区域数据的引用
    public  List<Area> InitialArea => GetInitialArea();

    /// <summary>
    /// 初始化数据
    /// </summary>
    /// <returns></returns>
    private List<Area> GetInitialArea()
    {
        return new List<Area>
        {
            new Area(110000,"北京市", 0, 1),
            new Area(110101,"东城区", 110100, 3),
            new Area(110102,"西城区", 110100, 3)
        };
    }

3.2 依赖注入方法容器里获取数据库上下文

构造函数,通过依赖注入容器拿到数据库上下文。

    //PEMS系统数据库上下文
    private readonly PEMSDbContext _context;

    /// <summary>
    /// 构造函数,通过依赖注入容器拿到数据库上下文
    /// </summary>
    /// <param name="context"></param>
    public DefaultAreaCreator(PEMSDbContext context)
    {
        _context = context;
    }

对依赖注入不明白的道友,可以参照此文 在net Core3.1上基于winform实现依赖注入实例

3.3 封装创建初始化数据列表方法

    /// <summary>
    /// 封装调用  创建初始化数据列表方法,这样上层调用看上去格式一致
    /// </summary>
    public void Create()
    {
        CreateArea();
    }
    /// <summary>
    /// 创建初始化数据列表方法
    /// </summary>
    private void CreateArea()
    {
        foreach (var area in InitialArea)
        {
            AddAreaIfNotExists(area);
        }
    }

遍历初始区域表,将数据加入到数据库中去。

3.4 数据库中没有的初始化数据,补充到数据库中去

通过数据库上下文,获取数据库中的区域id区域名称。与初始化数据对比,丢失的数据,添加到数据库里去。

    /// <summary>
    /// 某个区域记录缺失时,将该记录重新种入数据库进行持久化
    /// </summary>
    /// <param name="area"></param>
    private void AddAreaIfNotExists(Area area)
    {
        if (_context.Area.IgnoreQueryFilters().Any(a => a.Id== area.Id && a.AreaName == a.AreaName))
        {
            return;
        }
        _context.Area.Add(area);
        _context.SaveChanges();
    }  

4.效果

数据库中没有数据或者缺失某条或者某几条记录。结果都是如下初始数据。

5. Area实体

位于项目的领域层。

    /// <summary>
    /// Area实体类
    /// </summary>
    public class Area : Entity<long>
    {
        public Area()
        {
        }

        public Area(int id, string areaName, int parentID, int level)
        {
            this.Id = id;
            this.AreaName = areaName;
            this.ParentID = parentID;
            this.level = level;
        }

        [StringLength(20)]
        public string AreaName { get; set; }
        public int ParentID { get; set; }
        public int level { get; set; }

    }
  • Entity
    是Abp.Domain.Entities命名空间中的一个基类,可以指定Id的类型。
  • 需要如下构造函数为了方便初始化数据调用
        public Area(int id, string areaName, int parentID, int level)
        {
            this.Id = id;
            this.AreaName = areaName;
            this.ParentID = parentID;
            this.level = level;
        }
  • 另外还需要个空构造函数,为了EFCore能够正常使用。
        public Area()
        {
        }

6.小结

  • 本文提供了一种管理后台程序和数据库表结构和初始化数据的一种方案(基于EFCore)。不适合Dapper等半自动无法CodeFirst的ORM。
  • ABP框架的种子数据种入数据库,会获取到数据库上下文,扫描出表中缺失的数据,补录丢失的某条或者某几条记录。
posted @ 2020-03-06 17:59  JerryMouseLi  阅读(2977)  评论(0编辑  收藏  举报