背景
最近遇到一个小项目,前期需求比较简单,只有几个简单功能模块,但是后期需求又不太确定,而且时间催的紧,如果选用以前的框架的话,感觉比较重量级,如果使用简单的ADO.NET操作能解决,又担心后期扩展性的问题,由此想自己做一个轻量级的与业务无关的后台框架,保证使用简单又能便于后期扩展,于是Rookey.FastDevFrame v1.0诞生了。
框架思路
在通用三层框架的基础上保证各层的能够扩展,具体见下图:
以上框架基本实现,下面介绍下框架的特点
框架特点
(1)只有一个dll,小巧灵活,使用方便
(2)与业务实体无耦合,不依赖实体层
(3)可扩展性强,支持业务层重写,支持数据层重写,支持操作事件处理
(4)多种关系类型数据库支持,目前支持的数据库类型有mssql,可扩展支持mysql,oracle及其他
(5)支持非关系型数据库Mongodb,可扩展支持其他
(6)模块缓存可配置,支持本地缓存和Memcached分布式缓存,可扩展其他缓存方式
(7)支持SQL语句操作、支持Lamda表达式与SQL联合查询、支持读写分离
(8)实体层、数据层、业务层、操作事件层可配置
(9)在中小型项目中能极大提高开发效率
接下来给出实例讲解如何使用框架
使用框架
首先新建测试项目,为了演示方便建一个控制台程序
接下来在项目中新建实体类
1 /// <summary> 2 /// 流程信息表 3 /// </summary> 4 public class Dsg_ProcInfo 5 { 6 [PrimaryKey] 7 [AutoIncrement] 8 public long? Id { get; set; } 9 10 public string CreateUserName { get; set; } 11 12 public string ModifyUserName { get; set; } 13 14 public DateTime? CreateDate { get; set; } 15 16 public DateTime? ModifyDate { get; set; } 17 18 /// <summary> 19 /// 是否删除 20 /// </summary> 21 public bool IsDeleted { get; set; } 22 23 /// <summary> 24 /// 是否有效 25 /// </summary> 26 public bool IsValid { get; set; } 27 28 /// <summary> 29 /// 流程编码 30 /// </summary> 31 public string Code { get; set; } 32 33 /// <summary> 34 /// 流程名称 35 /// </summary> 36 public string Name { get; set; } 37 38 /// <summary> 39 /// 流程显示名称 40 /// </summary> 41 public string DisplayName { get; set; } 42 43 /// <summary> 44 /// 版本号 45 /// </summary> 46 public int Version { get; set; } 47 48 /// <summary> 49 /// 备注 50 /// </summary> 51 public string Memo { get; set; } 52 }
建完实体类就可以使用了,呵呵,就是这么简单
先在Program类中添加框架初始化配置方法:
1 /// <summary> 2 /// 初始化配置 3 /// </summary> 4 static void InitConfig() 5 { 6 //必须配置 7 FrameConfig.ModelAssemblyName = "Rookey.FastDevFrameTest"; 8 //可选择配置 9 FrameConfig.ModelNamespaceName = "FastDevFrameTest.Model"; 10 }
如果是在Web项目中,可以将配置方法放到Global.asax中
接下来初始化数据表,先在数据库新建数据库,名称随意,暂且叫FastDevFrame_Test
再在Program类中新建一个初始化数据表的方法
1 /// <summary> 2 /// 初始化数据表 3 /// </summary> 4 /// <returns></returns> 5 static bool InitTables() 6 { 7 string errMsg = string.Empty; 8 List<Type> modelTypes = BridgeObject.GetAllModelTypes(); 9 //修复数据表或字段 10 errMsg = InitOperate.CreateOrRepairTableFields(modelTypes); 11 return string.IsNullOrEmpty(errMsg); 12 }
最后在main方法中添加如下代码:
1 static void Main(string[] args) 2 { 3 InitConfig(); 4 if (InitTables()) 5 { 6 string errMsg = string.Empty; 7 //获取单个实体 8 Dsg_ProcInfo dsgInfo = CommonOperate.GetEntity<Dsg_ProcInfo>(x => x.Name == "测试流程", null, out errMsg); 9 if (dsgInfo == null) 10 { 11 dsgInfo = new Dsg_ProcInfo() { Code = "001", Name = "测试流程", DisplayName = "测试流程" }; 12 //新增实体 13 CommonOperate.OperateRecord<Dsg_ProcInfo>(dsgInfo, ModelRecordOperateType.Add, out errMsg); 14 } 15 } 16 }
在CommonOperate类中封装了常用的方法,后续再进行介绍。 下面介绍下自定义业务层、自定义操作处理及启用缓存功能首先在测试项目中新建业务接口IDsg_ProcInfoBLL.cs、业务实现Dsg_ProcInfoBLL.cs及自定义操作处理类Dsg_ProcInfoOperateHandle.cs,如下图示:
自定义业务接口添加一个简单的获取流程信息接口
public interface IDsg_ProcInfoBLL { Dsg_ProcInfo GetProInfo(string name); }
自定义业务类
1 class Dsg_ProcInfoBLL : BaseBLL<Dsg_ProcInfo>, IDsg_ProcInfoBLL 2 { 3 public Dsg_ProcInfoBLL() 4 { } 5 6 public override Dsg_ProcInfo GetEntity(out string errorMsg, Expression<Func<Dsg_ProcInfo, bool>> expression = null, string whereSql = null, string connString = null) 7 { 8 return base.GetEntity(out errorMsg, expression, whereSql, connString); 9 } 10 11 public Dsg_ProcInfo GetProInfo(string name) 12 { 13 string errMsg = string.Empty; 14 return this.Dal.GetEntity(out errMsg, x => x.Name == name); 15 } 16 }
重写了通用业务层GetEntity方法,并实现自定义业务接口方法
操作处理类IOperateHandle<Dsg_ProcInfo>
1 /// <summary> 2 /// 操作事件处理类 3 /// </summary> 4 class Dsg_ProcInfoOperateHandle : IOperateHandle<Dsg_ProcInfo> 5 { 6 /// <summary> 7 /// 单个实体操作(新增、修改、删除)后 8 /// </summary> 9 /// <param name="operateType">操作类型</param> 10 /// <param name="recordId">记录Id</param> 11 /// <param name="result">操作结果</param> 12 public void OperateCompeletedHandle(ModelRecordOperateType operateType, long recordId, bool result) 13 { 14 //单个实体操作(新增、修改、删除)完成后,做其他动作 15 return; 16 } 17 18 /// <summary> 19 /// 单个实体操作(新增、修改、删除)前处理 20 /// </summary> 21 /// <param name="operateType">操作类型</param> 22 /// <param name="t">实体对象</param> 23 /// <param name="errMsg">异常信息</param> 24 /// <returns></returns> 25 public bool BeforeOperateVerifyOrHandle(ModelRecordOperateType operateType, Dsg_ProcInfo t, out string errMsg) 26 { 27 errMsg = string.Empty; 28 //操作前,可以做业务逻辑验证 29 if (operateType == ModelRecordOperateType.Add) //如果是新增 30 { 31 } 32 return true; 33 } 34 35 /// <summary> 36 /// 多个实体操作(新增、修改、删除)后 37 /// </summary> 38 /// <param name="operateType"></param> 39 /// <param name="recordIds"></param> 40 /// <param name="result"></param> 41 public void OperateCompeletedHandles(ModelRecordOperateType operateType, List<long> recordIds, bool result) 42 { 43 //多个实体操作(新增、修改、删除)完成后,做其他动作 44 } 45 46 /// <summary> 47 /// 多个实体操作(新增、修改、删除)前处理 48 /// </summary> 49 /// <param name="operateType"></param> 50 /// <param name="ts"></param> 51 /// <param name="errMsg"></param> 52 /// <returns></returns> 53 public bool BeforeOperateVerifyOrHandles(ModelRecordOperateType operateType, List<Dsg_ProcInfo> ts, out string errMsg) 54 { 55 errMsg = string.Empty; 56 return true; 57 } 58 }
接下来将初化配置方法改成如下:
1 /// <summary> 2 /// 初始化配置 3 /// </summary> 4 static void InitConfig() 5 { 6 //必须配置 7 FrameConfig.ModelAssemblyName = "Rookey.FastDevFrameTest"; 8 //可选择配置 9 FrameConfig.ModelNamespaceName = "FastDevFrameTest.Model"; 10 //有自定义业务接口时需要配置 11 FrameConfig.IBllAssemblyName = "Rookey.FastDevFrameTest"; 12 //有自定义业务层重写时需要配置 13 FrameConfig.BllAssemblyName = "Rookey.FastDevFrameTest"; 14 //操作事件 15 FrameConfig.OperateHandleAssemblyName = "Rookey.FastDevFrameTest"; 16 //缓存配置 17 FrameConfig.IsEnableCache = true; 18 FrameConfig.CacheTableNames = new List<string>() { "Dsg_ProcInfo" }; 19 }
增加业务层、操作处理、缓存配置
最后修改main方法为
1 static void Main(string[] args) 2 { 3 InitConfig(); 4 if (InitTables()) 5 { 6 string errMsg = string.Empty; 7 //获取单个实体 8 Dsg_ProcInfo dsgInfo = CommonOperate.GetEntity<Dsg_ProcInfo>(x => x.Name == "测试流程", null, out errMsg); 9 if (dsgInfo == null) 10 { 11 dsgInfo = new Dsg_ProcInfo() { Code = "001", Name = "测试流程", DisplayName = "测试流程" }; 12 //新增实体 13 CommonOperate.OperateRecord<Dsg_ProcInfo>(dsgInfo, ModelRecordOperateType.Add, out errMsg); 14 15 //反射执行自定义业务层方法 16 object dsgObj = CommonOperate.ReflectExecuteBLLMethod(typeof(Dsg_ProcInfo), "GetProInfo", new object[] { "测试流程" }); 17 18 //非反射方式执行自定义业务层方法 19 IDsg_ProcInfoBLL procInfoBll = BridgeObject.Resolve<IDsg_ProcInfoBLL>(); 20 Dsg_ProcInfo info = procInfoBll.GetProInfo("测试流程"); 21 22 //自定义数据库连接 23 Dsg_ProcInfo obj = CommonOperate.GetEntity<Dsg_ProcInfo>(null, null, out errMsg); 24 Expression<Func<Dsg_ProcInfo, bool>> expression = x => x.Name == "测试流程"; 25 string connStr = "Data Source=127.0.0.1;Initial Catalog=FastDevFrame_Test;User ID=sa;Password=123456;Pooling=true;MAX Pool Size=512;Min Pool Size=50;Connection Lifetime=30"; 26 object tmpObj = CommonOperate.GetEntity("Dsg_ProcInfo", expression, null, out errMsg, connStr); 27 28 CommonOperate.DeleteRecordsByExpression<Dsg_ProcInfo>(x => x.Name == "测试流程", out errMsg); 29 } 30 } 31 }
是不是感觉很方便,不过由于所有层都在一个DLL中,也容易出现乱调用的情况,需要项目经理或负责人进行规范化。
本节对框架只做一个简单的介绍,在后面的章节中对各通用类及使用进行介绍,希望与有志于.NET开发的朋友多多交流学习。
最后附上源代码 Rookey.FastDevFrame_v1.0