zoukankan      html  css  js  c++  java
  • X-Admin&ABP框架开发-数据字典

      在业务型的系统开发中,我们需要维护各种个样的类型,比如客户类型、客户行业、商品类型等等,这些类型往往信息量不多,并且相似度极高,如果采用一类型一表去设计,将会造成极大的工作量,通过将这部分类型的信息进行抽象,利用字段去存储类型区分,共用表结构,来达到兼容各种类型的功能,也就是设计一个数据字典,而对于一个具体类型来讲,是有多个选项的,比如性别,有男女,行业有工农商等,对于这部分选项,可抽象为某个类型下的字典项,即数据字典项。

    一、数据字典设计思路

      1、从客户类型、商品类型、行业类型来抽象考虑,首先三者都存在一个类型描述,即客户、商品、行业,同时,三者是本质是不同的,并且,随着业务上的需求越来越多,更多的xx类型将会加入,因此,单从类型考虑出发,就存在三个点了,如类型名称、类型独立、数量扩展,因此在考虑表结构设计时,就可以先考虑到这三点了,同时还有一个关键的信息,便是,在系统设计过程中,这些类型其实便已经确定完毕了,而不是说,在开发完毕,再去系统中增加类型。

       

       2、从具体的某个类型出发考虑,比如以商品类型为例,存在日用品、电子产品、化妆品等,同样是存在几个关键信息,比如类型项名称、类型项独立、类型项数量扩展,类型项的归属,而这部分信息,往往是由客户去维护的,属于系统开发完毕后期的信息维护,在此,不考虑类型项的先后顺序问题,如有需要可以扩展。

       

      按照这些信息点,可以对数据字典设计一些必要的字段,如类型名称即TypeName、 类型独立便是类型间相互独立,但是这里也存在一个类型间的上下父子问题,暂不加入进来,该父子问题使用场景较少,但又存在,如果按照“二八原则”的话,我还是喜欢把“八”的部分完成。对于数据字典项而言,按照给定的必要信息,设计成如下结构,其中的业务代码,是需要唯一的,比如对于性别来将,业务代码便是1或0,来代表男女,这部分可由客户的系统管理员进行维护。

      

    二、完成数据字典设计

       在明确了这些基础信息后,开始在项目中完成设计过程,首先得明确数据字典本身的归属,数据字典是为整个业务而服务的,因此我把它划分到核心层这一级别中,首先在领域层设置Core层文件夹,用来存放为整个业务提供基础设施的功能模块。

       

      1、在Core层中加入数据字典模块,结构设计如:

      

      开始创建数据字典类,并添加设计的字段,以保证够用为前提,或许更多场景下会出现诸如父子字典情形,或是对字典内容的描述等,暂不考虑。

    /// <summary>
    /// 核心_数据字典
    /// </summary>
    [Table("Core_DataDictionary")]
    public class DataDictionary : Entity<long>
    {
        public const int MaxNameLength = 30;
    
        /// <summary>
        /// 字典类型
        /// </summary>
        [StringLength(MaxNameLength)]
        public string TypeName { get; set; }
    
        /// <summary>
        /// 关联数据字典项
        /// </summary>
        public virtual ICollection<DataDictionaryItem> DataDictionaryItem { get; set; }
    }

       在增加数据字典项类,并添加设计时的字段信息,这里我通过数据注解完成对字段的一些约束,如长度约束,表名的映射等。

    /// <summary>
    /// 核心_数据字典项
    /// </summary>
    [Table("Core_DataDictionaryItem")]
    public class DataDictionaryItem : Entity<long>
    {
        public const int MaxCodeLength = 5;
        public const int MaxNameLength = 30;
    
        /// <summary>
        /// 业务代码
        /// </summary>
        [StringLength(MaxCodeLength)]
        public string Code { get; set; }
    
        /// <summary>
        /// 类型项名称
        /// </summary>
        [StringLength(MaxNameLength)]
        public string Name { get; set; }
    
        /// <summary>
        /// 数据字典Id
        /// </summary>
        public long DataDictionaryId { get; set; }
    
        /// <summary>
        /// 关联数据字典项
        /// </summary>
        public virtual DataDictionary DataDictionary { get; set; }
    }

      加入到DbContext中,添加一个迁移并更新数据库。

      

      2、开始完成应用层的封装工作,在应用层定义了几个常用的对字典的一些操作,诸如添加删除修改等常见操作,此处的数据字典暂时通过手动加入,而不是将已有数据字典或是更改了的数据字典自动更新到数据库中。

    /// <summary>
    /// 获取数据字典集合
    /// </summary>
    /// <returns></returns>
    Task<ListResultDto<DataDictionaryListDto>> GetAllDataDictionaryListAsync();
    
    /// <summary>
    /// 获取数据字典记录
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    Task<DataDictionaryEditDto> GetDataDictionaryForEditAsync(NullableIdDto<long> input);
    
    /// <summary>
    /// 添加或更新数据字典记录
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    Task CreateOrUpdateDataDictionaryAsync(CreateOrUpdateDataDictionaryInput input);
    
    /// <summary>
    /// 删除数据字典记录
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    Task DeleteDataDictionaryAsync(List<EntityDto<long>> inputs);
    
    /// <summary>
    /// 根据字典类型名称获取数据字典集合
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    Task<ListResultDto<DataDictionaryListDto>> GetDataDictionaryListByTypeNamesAsync(GetDataDictionaryListByTypeNamesInput input);

       对数据字典项也准备了几个方法,用于对某一具体数据字典类型增加删除修改数据字典项。

    /// <summary>
    /// 获取数据字典项
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    Task<DataDictionaryItemEditDto> GetDataDictionaryItemForEditAsync(NullableIdDto<long> input);
    
    /// <summary>
    /// 添加或更新数据字典项
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    Task CreateOrUpdateDataDictionaryItemAsync(CreateOrUpdateDataDictionaryItemInput input);
    
    /// <summary>
    /// 删除数据字典项
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    Task DeleteDataDictionaryItemAsync(List<EntityDto<long>> inputs);
    
    /// <summary>
    /// 根据字典类型和字典项名称获取字典项值
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    Task<GetDataDictionaryItemNameOutput> GetDataDictionaryItemNameAsync(GetDataDictionaryItemNameInput input);
    
    /// <summary>
    /// 获取数据字典列表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    Task<ListResultDto<DataDictionaryItemListDto>> GetDataDictionaryItemListAsync(GetDataDictionaryItemListInput input);

       在应用层建立一个全局常量数据字典类,用于存储数据字典信息,该部分信息也将成为需要维护到系统中的必备信息,并且,在系统中如有地方需要调用到数据字典类型时,不需要写死代码。

    /// <summary>
    /// 数据字典类型存储表
    /// </summary>
    public class DataDictionaryTypeConsts
    {
        #region 分瓶规则
        public const string GroupRule_FixAtive = "固定剂及使用";
    
        public const string GroupRule_ContainerType = "容器类型";
        #endregion
    }

       3、完成控制器层调用及页面中对数据字典的管理 ,对于字典信息而言,足够在界面中一览全貌,因此页面设计时,直接以树形结构加表格展示即可,左侧数据类型树形结构,右侧相应的数据类型项表格。

    <div class="layui-row">
        <div class="layui-col-md2 layui-col-xs12">
            <ul id="tree" class="ztree" style="padding: 0px; border: 1px solid #ddd; overflow: auto;"></ul>
        </div>
        <div class="layui-col-md10 layui-col-xs12">
            <table class="layui-table"
                    lay-data="{height: 'full-180', page:true, id:'mainList'}"
                    lay-filter="list" lay-size="xs">
                <thead>
                    <tr>
                        <th lay-data="{checkbox:true, fixed: true}"></th>
                        <th lay-data="{field:'code', sort: true}">业务代码</th>
                        <th lay-data="{field:'name'}">名称</th>
                        @if (await PermissionChecker.IsGrantedAsync(PermissionNames.Pages_Core_DataDictionaryItem_Edit) ||
                    await PermissionChecker.IsGrantedAsync(PermissionNames.Pages_Core_DataDictionaryItem_Delete))
                        {
                            <th lay-data="{fixed:'right', align:'center', toolbar: '#barList'}"></th>
                        }
                    </tr>
                </thead>
            </table>
        </div>
    </div>

    三、数据字典页面展示

      利用layui节省了不少时间,对于前端东西不太精通,只能够用,勉强实现了数据字典的一些操作,其中的数据字典类型是按照开发过程中可能用到的进行加入的,合理的存在,而不是空穴来风,在之前的DataDictionaryConst类中可以定义需要用到的数据字典类型,此处并没有直接从那里增加后自动导入到数据库中。 

     至此,数据字典的初步逻辑设计完毕,至于要加入更为丰富的功能,诸如排序,父子数据类型,或是数据类型描述,均可扩展。 

     代码地址:https://gitee.com/530521314/Partner.Surround.git

    2019-07-07,望技术有成后能回来看见自己的脚步
  • 相关阅读:
    2021,6,10 xjzx 模拟考试
    平衡树(二)——Treap
    AtCoder Beginner Contest 204 A-E简要题解
    POJ 2311 Cutting Game 题解
    Codeforces 990G GCD Counting 题解
    NOI2021 SDPTT D2T1 我已经完全理解了 DFS 序线段树 题解
    第三届山东省青少年创意编程与智能设计大赛总结
    Luogu P6042 「ACOI2020」学园祭 题解
    联合省选2021 游记
    Codeforces 1498E Two Houses 题解 —— 如何用结论吊打标算
  • 原文地址:https://www.cnblogs.com/CKExp/p/11107312.html
Copyright © 2011-2022 走看看