Within the module for high poly? Low coupling between modules? MVC + EF show you!

Foreword  

  In the software development process, we always hear "high cohesion, low coupling", even if this idea in the process of learning to program in our monasteries have been. But once when we on the project, we will finish the work of "lazy", to save time on the province. Who cares what the design patterns, what software architecture to achieve on the line to say. Of course, if this is a one-time project, or is a relatively simple project, better said, but if the project involves the redevelopment of post-maintenance, "lazy" So before it will become a "technical debt." EF recently finished research framework, write a demo to practice your hand, just to serve as a stimulus to be posted. I hope we can discuss common progress!

Basic framework to build

  Infrastructure is commonly used three-tier architecture, UI layer: MVC, database access driver layer: Entity Framework, because it is here in our Model presentation layer to use two tables do demonstrate (T_UserInfo, T_OrderInfo)

 Database access layer design

  After the basic framework set up is completed, we'll design it to access the database driver layer DAL. First, we abstract a BaseDAL, write a common CRUD.

 1 namespace Smp.Demo.EFDAL
 2 {
 3     public class BaseDal<T> where T : class,new()
 4     {
 5         SmpDBEntities m_dbContext = new SmpDBEntities();
 6 
 7         // 条件查询
 8         public virtual IQueryable<T> GetEntities(Expression<Func<T, bool>> whereLambda)
 9         {
10             return m_dbContext.Set<T>().Where(whereLambda);
11         }
12 
13         // 分页查询
14         public virtual IQueryable<T> GetPageEntities<S>(int pageSize, int pageIndex, out int totalCount,
15             Func<T, bool> whereLambda, Func<T, S> orderLambda)
16         {
17             totalCount = m_dbContext.Set<T>().Count();
18             return m_dbContext.Set<T>().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<T>().Add(dbInfo);
27             m_dbContext.SaveChanges();
28             return dbInfo;
29         }
30 
31         // 删除
32         public virtual bool Delete(T dbInfo)
33         {
34             m_dbContext.Entry<T>(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 }

 Then we package T_UserInfo and T_OrderInfo database access layer, the direct successor to BaseDAL, following Cheng Houzai class with special needs can achieve alone.

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

 Business Logic Layer Design 

  Business logic layer in three-layer architecture in right weight is relatively high layer, the layer plays a connecting role in the project, it is necessary to operate CRUD data access layer, business logic but also UI layer. So then we have to demonstrate Demo T_UserInfo to write a business logic layer

. 1  namespace Smp.Demo.BLL
 2  {
 . 3      public  class T_UserInfoBLL
 . 4      {
 . 5          T_UserInfoDAL m_userInfoDAL = new new T_UserInfoDAL ();
 . 6  
. 7          // get all user information 
. 8          public List <T_UserInfo> GetAllUserInfo ()
 . 9          {
 10              return m_userInfoDAL.GetEntities (the userInfo => to true ) .ToList ();
 . 11          }
 12 is  
13 is          // add a new user and returns the user ID 
14          public  int the AddUser (T_UserInfo the 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 }

When we frame the DAL and the BLL's finished, we create a test unit in the current project, whether more testing framework to function properly

 After testing, for now we can build the architecture is running properly, we look at the UML diagram between the DAL and the BLL current

 Think

  通过以上的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<T> where T : class ,new()
 4     {
 5         // 条件查询
 6         IQueryable<T> GetEntities(Expression<Func<T, bool>> whereLambda);
 7 
 8         // 条件分页查询
 9         IQueryable<T> GetPageEntities<S>(int pageSize, int pageIndex, out int totalCount,
10            Func<T, bool> whereLambda, Func<T, S> 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<T_UserInfo>
 4     {
 5     }
 6 }
 7 
 8 namespace Smp.Demo.IDAL
 9 {
10     public interface IOrderInfo : IBaseDAL<T_OrderInfo>
11     {
12     }
13 }

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

 1 namespace Smp.Demo.EFDAL
 2 {
 3     public class T_OrderInfoDAL : BaseDal<T_OrderInfo>,IOrderInfo
 4     {
 5 
 6     }
 7 }
 8 
 9 namespace Smp.Demo.EFDAL
10 {
11     public class T_UserInfoDAL : BaseDal<T_UserInfo>,IUserInfo
12     {
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<T_UserInfo> GetAllUserInfo()
 9         {
10             return m_userInfoDAL.GetEntities(userInfo => true).ToList();
11         }
12 
13         // 添加用户并返回新增用户ID
14         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 <!DOCTYPE html>
21 
22 <html>
23 <head>
24     <title>Index</title>
25 </head>
26 <body>
27     <div>
28         @foreach (var item in ViewData["users"] as List<Smp.Demo.Model.T_UserInfo>)
29         {
30             <p>
31                 @item.UserName
32             </p>
33         }
34     </div>
35 </body>
36 </html>

最后效果

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

源码下载地址:https://github.com/p9966/Smp.Demo

Guess you like

Origin www.cnblogs.com/insipid/p/11116844.html
Recommended