博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
模块内高内聚?模块间低耦合?MVC+EF演示给你看!
阅读量:4325 次
发布时间:2019-06-06

本文共 6878 字,大约阅读时间需要 22 分钟。

前言  

  在软件项目开发过程中,我们总能听见“高内聚,低耦合”,即使这种思想在我们学习编程的过程中就已经耳濡目染。可一旦当我们上项目,赶进度的时候我们就会“偷懒”,能省时间就省。管他什么设计模式,什么软件架构先实现上线再说。当然,如果这是一个一次性项目,或者是一个比较简单的项目还好说,但如果这个项目牵扯到后期的维护再开发,那么之前的“偷懒”就会成为“技术债”。最近刚研究完EF框架,写个demo练练手,正好贴出来做个抛砖引玉的作用。希望大家一起讨论,共同进步!

基础框架搭建

  基础架构也就是常用的三层架构,UI层:MVC,数据库访问驱动层:Entity Framework,由于是演示在这里我们的Model层就用两个表做演示了(T_UserInfo,T_OrderInfo)

 数据库访问层设计

  在基础框架搭建完毕后,我们再设计一下数据库访问驱动层DAL。首先我们抽象一个BaseDAL,写一个公共的CRUD。

1 namespace Smp.Demo.EFDAL 2 { 3     public class BaseDal
where T : class,new() 4 { 5 SmpDBEntities m_dbContext = new SmpDBEntities(); 6 7 // 条件查询 8 public virtual IQueryable
GetEntities(Expression
> whereLambda) 9 {10 return m_dbContext.Set
().Where(whereLambda);11 }12 13 // 分页查询14 public virtual IQueryable
GetPageEntities
(int pageSize, int pageIndex, out int totalCount,15 Func
whereLambda, Func
orderLambda)16 {17 totalCount = m_dbContext.Set
().Count();18 return m_dbContext.Set
().Where(whereLambda).19 OrderBy(orderLambda).Skip((pageIndex - 1) * pageSize).20 Take(pageSize * pageIndex).AsQueryable();21 }22 23 // 添加24 public virtual T Add(T dbInfo)25 {26 m_dbContext.Set
().Add(dbInfo);27 m_dbContext.SaveChanges();28 return dbInfo;29 }30 31 // 删除32 public virtual bool Delete(T dbInfo)33 {34 m_dbContext.Entry
(dbInfo).State = System.Data.EntityState.Deleted;35 return m_dbContext.SaveChanges() > 0;36 }37 38 // 修改39 public virtual bool Update(T dbInfo)40 {41 m_dbContext.Entry(dbInfo).State = System.Data.EntityState.Modified;42 return m_dbContext.SaveChanges() > 0;43 }44 }45 }

 然后我们封装T_UserInfo和T_OrderInfo的数据库访问层,直接继承BaseDAL即可,继承后子类中有特殊需求单独实现即可。

1 namespace Smp.Demo.EFDAL 2 { 3     public class T_UserInfoDAL : BaseDal
4 { 5 6 } 7 } 8 9 namespace Smp.Demo.EFDAL10 {11 public class T_OrderInfoDAL : BaseDal
12 {13 14 }15 }

 业务逻辑层设计 

  业务逻辑层在三层架构中权重是比较高的一层,该层在项目中起到一个承上启下的作用,既要操作数据访问层的CRUD,也要处理UI层的业务逻辑。那么接下来我们就以T_UserInfo来写一个业务逻辑层的演示Demo

1 namespace Smp.Demo.BLL 2 { 3     public class T_UserInfoBLL 4     { 5         T_UserInfoDAL m_userInfoDAL = new T_UserInfoDAL(); 6  7         // 获取全部用户信息 8         public List
GetAllUserInfo() 9 {10 return m_userInfoDAL.GetEntities(userInfo => true).ToList();11 }12 13 // 添加用户并返回新增用户ID14 public int AddUser(T_UserInfo userInfo)15 {16 var l_newUserInfo = m_userInfoDAL.Add(userInfo);17 return l_newUserInfo.ID;18 }19 20 // 删除指定用户21 public bool Delete(T_UserInfo userInfo)22 {23 return m_userInfoDAL.Delete(userInfo);24 }25 }26 }

当我们DAL层和BLL层的框架写完后,我们在当前项目中创建一个测试单元,测试以上框架是否能够正常运行

 经测试,就目前而言我们搭建的架构是可以正常运行的,那么我们来看一下当前DAL层和BLL层之间的UML图

 思考

  通过以上的UML图和代码我们可以看到,每个模块都相对独立,基本上完成了“高内聚”的思想。但唯一不足的就是BLL层和DAL之间的连接总是不那么尽如人意。例如存在这样的需求,当用户量大了以后DAL层想从EF框架换为NH框架,或者是想将数据库从SqlServer换为Oracle。那么我们以上的设计是不符合“低耦合”思想的,因为BLL层和DAL层的依赖是那么的强,一旦数据库访问驱动层更换那么BLL层和DAL层的改动是非常多的。怎么办呢?我想大家在开发过程中可能听过这么一句话“面向接口编程”。那么我们也来对BLL层和DAL层之间面向接口编程吧!

数据访问驱动层接口设计

  首先,在当前项目中新增一个“IDAL”接口项目。然后我们对DAL层的CRUD来进行一个抽象。

1 namespace Smp.Demo.IDAL 2 { 3     public interface IBaseDAL
where T : class ,new() 4 { 5 // 条件查询 6 IQueryable
GetEntities(Expression
> whereLambda); 7 8 // 条件分页查询 9 IQueryable
GetPageEntities
(int pageSize, int pageIndex, out int totalCount,10 Func
whereLambda, Func
orderLambda);11 12 // 添加13 T Add(T dbInfo);14 15 // 删除16 bool Delete(T dbInfo);17 18 // 更新19 bool Update(T dbInfo);20 }21 }

其次我们再继承“IDAL”写IUserInfo和IOrderInfo数据库访问驱动层接口

1 namespace Smp.Demo.IDAL 2 { 3     public interface IUserInfo : IBaseDAL
4 { 5 } 6 } 7 8 namespace Smp.Demo.IDAL 9 {10 public interface IOrderInfo : IBaseDAL
11 {12 }13 }

 然后我们再将EFDAL层中的T_OrderInfoDAL和T_UserInfoDAL再分别继承IUserInfo和IOrderInfo

1 namespace Smp.Demo.EFDAL 2 { 3     public class T_OrderInfoDAL : BaseDal
,IOrderInfo 4 { 5 6 } 7 } 8 9 namespace Smp.Demo.EFDAL10 {11 public class T_UserInfoDAL : BaseDal
,IUserInfo12 {13 14 }15 }

 重新设计后UML图是这样的,也就是在BLL层和DAL层之间加了个中间层,方便后期动态配置数据访问驱动层。降低耦合程度

 当我们将接口设计好后,我们再在当前项目下创建一个DALFactory抽象工厂项目,用于后期基于Web.config文件动态获取DAL层访问

抽象工厂模式的创建

  第一步、打开UI层在Web.confg文件中找到appSettings节点中添加后期动态创建的DAL层程序集节点名称方便后期反射指定程序集

  第二步、创建一个新建项目DALFactory抽象工厂,用户按照Web.config动态创建指定DAL数据库访问驱动

1 namespace Smp.Demo.DALFactory 2 { 3     public static class StaticDALFactory 4     { 5         public static IUserInfo GetUserInfoDAL() 6         { 7             string l_strAssemblyName = System.Configuration.ConfigurationManager.AppSettings["AssemblyName"]; 8             return Assembly.Load(l_strAssemblyName).CreateInstance(l_strAssemblyName + ".T_UserinfoDAL") as IUserInfo; 9         }10 11         public static IOrderInfo GetOrderInfoDAL()12         {13             string l_strAssemblyName = System.Configuration.ConfigurationManager.AppSettings["AssemblyName"];14             return Assembly.Load(l_strAssemblyName).CreateInstance(l_strAssemblyName + ".T_Orderinfo") as IOrderInfo;15         }16     }17 }

  第三步、修改BLL层中访问DAL层的访问方式

1 namespace Smp.Demo.BLL 2 { 3     public class T_UserInfoBLL 4     { 5         IUserInfo m_userInfoDAL = StaticDALFactory.GetUserInfoDAL(); 6  7         // 获取全部用户信息 8         public List
GetAllUserInfo() 9 {10 return m_userInfoDAL.GetEntities(userInfo => true).ToList();11 }12 13 // 添加用户并返回新增用户ID14 public int AddUser(T_UserInfo userInfo)15 {16 var l_newUserInfo = m_userInfoDAL.Add(userInfo);17 return l_newUserInfo.ID;18 }19 20 // 删除指定用户21 public bool Delete(T_UserInfo userInfo)22 {23 return m_userInfoDAL.Delete(userInfo);24 }25 }26 }

  第四步、将EFDAL中app.config的连接字符串配置到UI层web.config中

  第五步、在UI层中创建一个demo控制器,并同时创建一个Index视图

1 namespace Smp.Demo.UI.Controllers 2 { 3     public class DemoController : Controller 4     { 5         // 6         // GET: /Demo/ 7         public ActionResult Index() 8         { 9             var Users = new T_UserInfoBLL().GetAllUserInfo();10             ViewData["users"] = Users;11             return View();12         }13     }14 }15 16 @{17     Layout = null;18 }19 20 21 22 23 24     Index25 26 27     
28 @foreach (var item in ViewData["users"] as List
)29 {30

31 @item.UserName32

33 }34
35 36

最后效果

 这样的话后期我们就可以很方便的扩展数据访问层啦!

源码下载地址:

转载于:https://www.cnblogs.com/insipid/p/11116844.html

你可能感兴趣的文章
小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-3.微信Oauth2.0交互流程讲解...
查看>>
小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_3-5.PageHelper分页插件使用
查看>>
小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-6.微信扫码登录回调本地域名映射工具Ngrock...
查看>>
小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_4-2.微服务下登录检验解决方案 JWT讲解...
查看>>
小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-8.用户模块开发之保存微信用户信息...
查看>>
HDU 5353 Average
查看>>
进程和计划管理
查看>>
MQ_ActiveMQ环境部署+C#推送和接收消息
查看>>
Ubuntu16.04上使用Anaconda3的Python3.6的pip安装UWSGI报错解决办法
查看>>
学习笔记11.6
查看>>
高效中的细节注意
查看>>
MySQL 之 库操作
查看>>
Python 最抢手、Java 最流行,前线程序员揭秘 2019 软件开发现状
查看>>
R语言(一)
查看>>
商品搜索引擎---分词(插件介绍与入门实例)
查看>>
win7下硬盘安装Windows
查看>>
SQL Server 数据库性能优化(转载)
查看>>
java ee课程目标
查看>>
Shell 脚本进程并发&进程数控制
查看>>
Java基础String类
查看>>