在业务型的系统开发中,咱们须要维护各类个样的类型,好比客户类型、客户行业、商品类型等等,这些类型每每信息量很少,而且类似度极高,若是采用一类型一表去设计,将会形成极大的工做量,经过将这部分类型的信息进行抽象,利用字段去存储类型区分,共用表结构,来达到兼容各类类型的功能,也就是设计一个数据字典,而对于一个具体类型来说,是有多个选项的,好比性别,有男女,行业有工农商等,对于这部分选项,可抽象为某个类型下的字典项,即数据字典项。前端
一、从客户类型、商品类型、行业类型来抽象考虑,首先三者都存在一个类型描述,即客户、商品、行业,同时,三者是本质是不一样的,而且,随着业务上的需求愈来愈多,更多的xx类型将会加入,所以,单从类型考虑出发,就存在三个点了,如类型名称、类型独立、数量扩展,所以在考虑表结构设计时,就能够先考虑到这三点了,同时还有一个关键的信息,即是,在系统设计过程当中,这些类型其实便已经肯定完毕了,而不是说,在开发完毕,再去系统中增长类型。java
二、从具体的某个类型出发考虑,好比以商品类型为例,存在日用品、电子产品、化妆品等,一样是存在几个关键信息,好比类型项名称、类型项独立、类型项数量扩展,类型项的归属,而这部分信息,每每是由客户去维护的,属于系统开发完毕后期的信息维护,在此,不考虑类型项的前后顺序问题,若有须要能够扩展。git
按照这些信息点,能够对数据字典设计一些必要的字段,如类型名称即TypeName、 类型独立即是类型间相互独立,可是这里也存在一个类型间的上下父子问题,暂不加入进来,该父子问题使用场景较少,但又存在,若是按照“二八原则”的话,我仍是喜欢把“八”的部分完成。对于数据字典项而言,按照给定的必要信息,设计成以下结构,其中的业务代码,是须要惟一的,好比对于性别来将,业务代码即是1或0,来表明男女,这部分可由客户的系统管理员进行维护。数据库
在明确了这些基础信息后,开始在项目中完成设计过程,首先得明确数据字典自己的归属,数据字典是为整个业务而服务的,所以我把它划分到核心层这一级别中,首先在领域层设置Core层文件夹,用来存放为整个业务提供基础设施的功能模块。ui
一、在Core层中加入数据字典模块,结构设计如:spa
开始建立数据字典类,并添加设计的字段,以保证够用为前提,或许更多场景下会出现诸如父子字典情形,或是对字典内容的描述等,暂不考虑。设计
/// <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; } }
在增长数据字典项类,并添加设计时的字段信息,这里我经过数据注解完成对字段的一些约束,如长度约束,表名的映射等。3d
/// <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中,添加一个迁移并更新数据库。code
二、开始完成应用层的封装工做,在应用层定义了几个经常使用的对字典的一些操做,诸如添加删除修改等常见操做,此处的数据字典暂时经过手动加入,而不是将已有数据字典或是更改了的数据字典自动更新到数据库中。blog
/// <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 }
三、完成控制器层调用及页面中对数据字典的管理 ,对于字典信息而言,足够在界面中一览全貌,所以页面设计时,直接以树形结构加表格展现便可,左侧数据类型树形结构,右侧相应的数据类型项表格。
<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,望技术有成后能回来看见本身的脚步