多層架構+MVC+EF+AUTOFAC+AUTOMAPPER

 

 

  最近使用ligerui搭建了一个简单的教务管理demo,将重要的地方记录,也希望能幫到有这方面需要园友。


一、目录

 1、多层架构+MVC+EF+AUTOFAC+AUTOMAPPER;

 2、MVC中验证码的实现(经常用,记录备用)

二、正文

 多层架构中等以上规模以上的系统用得比较多,此demo功能不多,出于抱着学习的态度搭建了一个多层架构,并加入现在很流行的依赖倒转(autofac)、对象映射工具(automapper)。

 话说没图你说个J8,先上框架图:

多層架構+MVC+EF+AUTOFAC+AUTOMAPPER

  Model层中Entity存放数据库实体,使用code first,ViewModel存放界面展示模型。DAL层中IDAO存放接口,EFDAO实现IDAO。BLL结构与DAL类似,接口+实现。WEB层就是我们的UI层了,在这个框架中,WEB层使用MVC。什么,MVC不就是多层架构嘛,怎么还把它放Web层呢?MVC并不等同于多层架构,有这样疑问的同学,请在园内搜索相关文章。Infrastructure层是我们的基础设施层,我把一些常用的工具类封装后放入其中,方便其它地方调用。

  IDao中定义了一个公共基类,基类中定义所有子类都会用到的查询方法:

多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
 1 namespace YTJWGL_IDao
 2 {
 3     public interface IBaseDao<T>
 4     {
 5         #region 查询普通实现方案(基于Lambda表达式的Where查询)
 6         /// <summary>
 7         /// 获取所有Entity
 8         /// </summary>
 9         /// <param name="exp">Lambda条件的where</param>
10         /// <returns></returns>
11         IEnumerable<T> GetEntities(Func<T, bool> exp);
12 
13         /// <summary>
14         /// 计算总个数(分页)
15         /// </summary>
16         /// <param name="exp">Lambda条件的where</param>
17         /// <returns></returns>
18         int GetEntitiesCount(Func<T, bool> exp);
19 
20         /// <summary>
21         /// 分页查询(Linq分页方式)
22         /// </summary>
23         /// <param name="pageNumber">当前页</param>
24         /// <param name="pageSize">页码</param>
25         /// <param name="orderName">lambda排序名称</param>
26         /// <param name="sortOrder">排序(升序or降序)</param>
27         /// <param name="exp">lambda查询条件where</param>
28         /// <returns></returns>
29         IEnumerable<T> GetEntitiesForPaging(int pageNumber, int pageSize, Func<T, string> orderName, string sortOrder, Func<T, bool> exp);
30 
31         /// <summary>
32         /// 根据条件查找
33         /// </summary>
34         /// <param name="exp">lambda查询条件where</param>
35         /// <returns></returns>
36         T GetEntity(Func<T, bool> exp);
37 
38         #endregion
39 
40         //#endregion
41         /// <summary>
42         /// 插入Entity
43         /// </summary>
44         /// <param name="model"></param>
45         /// <returns></returns>
46         bool Insert(T entity);
47         /// <summary>
48         /// 更新Entity
49         /// </summary>
50         /// <param name="model"></param>
51         /// <returns></returns>
52         bool Update(T entity);
53         /// <summary>
54         /// 删除Entity
55         /// </summary>
56         /// <param name="entity"></param>
57         /// <returns></returns>
58         bool Delete(T entity);
59         /// <summary>
60         /// 删除实现 存储过程实现方式(调用spDelete+表名+ 主键ID)
61         /// </summary>
62         /// <param name="ID">删除的主键</param>
63         /// <returns></returns>
64         //bool Delete(object ID);
65     }
66 }
多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
IDAO

  EFDao有一个类实现这一公共基类:

多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
  1 namespace YTJWGL_EFDao
  2 {
  3     public class BaseEFDao<T> : IBaseDao<T> where T : class,new()//限制T的类型为class或者对象
  4     {
  5 
  6 
  7         #region 查询普通实现方案(基于Lambda表达式的Where查询)
  8         /// <summary>
  9         /// 获取所有Entity
 10         /// </summary>
 11         /// <param name="exp">Lambda条件的where</param>
 12         /// <returns>返回IEnumerable类型</returns>
 13         public virtual IEnumerable<T> GetEntities(Func<T, bool> exp)
 14         {
 15             using (Entities db = new Entities())
 16             {
 17                 return db.Set<T>().Where(exp).ToList();
 18             }
 19 
 20 
 21         }
 22         /// <summary>
 23         /// 计算总个数(分页)
 24         /// </summary>
 25         /// <param name="exp">Lambda条件的where</param>
 26         /// <returns></returns>
 27         public virtual int GetEntitiesCount(Func<T, bool> exp)
 28         {
 29             using (Entities db = new Entities())
 30             {
 31                 return db.Set<T>().Where(exp).ToList().Count();
 32 
 33             }
 34         }
 35         /// <summary>
 36         /// 分页查询(Linq分页方式)
 37         /// </summary>
 38         /// <param name="pageNumber">当前页</param>
 39         /// <param name="pageSize">页码</param>
 40         /// <param name="orderName">lambda排序名称</param>
 41         /// <param name="sortOrder">排序(升序or降序)</param>
 42         /// <param name="exp">lambda查询条件where</param>
 43         /// <returns></returns>
 44         public virtual IEnumerable<T> GetEntitiesForPaging(int pageNumber, int pageSize, Func<T, string> orderName, string sortOrder, Func<T, bool> exp)
 45         {
 46             using (Entities db = new Entities())
 47             {
 48                 if (sortOrder == "asc") //升序排列
 49                 {
 50                     return db.Set<T>().Where(exp).OrderBy(orderName).Skip((pageNumber - 1) * pageSize).Take(pageSize).ToList();
 51                 }
 52                 else
 53                 {
 54                     return db.Set<T>().Where(exp).OrderByDescending(orderName).Skip((pageNumber - 1) * pageSize).Take(pageSize).ToList();
 55                 }
 56             }
 57 
 58         }
 59         /// <summary>
 60         /// 根据条件查找满足条件的一个entites
 61         /// </summary>
 62         /// <param name="exp">lambda查询条件where</param>
 63         /// <returns></returns>
 64         public virtual T GetEntity(Func<T, bool> exp)
 65         {
 66             using (Entities db = new Entities())
 67             {
 68                 return db.Set<T>().Where(exp).SingleOrDefault();
 69             }
 70         }
 71         #endregion
 72 
 73         #region 增改删实现
 74         /// <summary>
 75         /// 插入Entity
 76         /// </summary>
 77         /// <param name="model"></param>
 78         /// <returns></returns>
 79         public virtual bool Insert(T entity)
 80         {
 81             using (Entities db = new Entities())
 82             {
 83                 var obj = db.Set<T>();
 84                 obj.Add(entity);
 85                 return db.SaveChanges() > 0;
 86 
 87             }
 88 
 89         }
 90         /// <summary>
 91         /// 更新Entity(注意这里使用的傻瓜式更新,可能性能略低)
 92         /// </summary>
 93         /// <param name="model"></param>
 94         /// <returns></returns>
 95         public virtual bool Update(T entity)
 96         {
 97             using (Entities db = new Entities())
 98             {
 99                 var obj = db.Set<T>();
100                 obj.Attach(entity);
101                 db.Entry(entity).State = System.Data.EntityState.Modified;
102                 return db.SaveChanges() > 0;
103             }
104 
105 
106         }
107         /// <summary>
108         /// 删除Entity
109         /// </summary>
110         /// <param name="entity"></param>
         /// <returns></returns>
112         public virtual bool Delete(T entity)
113         {
114             using (Entities db = new Entities())
115             {
116                 var obj = db.Set<T>();
117                 if (entity != null)
118                 {
119                     obj.Attach(entity);
120                     db.Entry(entity).State = System.Data.EntityState.Deleted;
121                     obj.Remove(entity);
122                     return db.SaveChanges() > 0;
123                 }
124                 return false;
125             }
126 
127         }
128         #endregion
129     }
130 }
EFDAO

  可以看到,代码中都是使用的泛型。根据传入的实体类型决定访问莫一数据实体。

  倘若,我们有一个数据实体类叫做Admin,IDAO,EFDAO中可以分别添加Admin对应的DAL层文件:

多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
1 namespace YTJWGL_IDao
2 {
3     public interface IAdminDao<T> : IBaseDao<T> where T : class
4     {
5 
6     }
7 }
IAdminDao
多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
1 namespace YTJWGL_EFDao
2 {
3     public class AdminEFDao : BaseEFDao<YTJWGL_Admin>, IAdminDao<YTJWGL_Admin>
4     {
5     }
6 }
AdminEFDao

   IAdminDao继承我们上面定义的公共接口,AdminEFDao继承IAdminDao接口以及BaseEFDao基类,这样我们可以在IAdminDao中定义该数据实体特有的查询方法,同时复用了我们常用的查询以及增加、删除、编辑代码。至于为什么要使用接口,是为了满足面向对象原则的依赖倒转原则——抽象不依赖细节,细节应该依赖抽象。

  BLL层代码结构与DAL类似。

  一个简单的多层架构就是这样,各层之间引用关系从顶层向下调用底层,将各层之间耦合尽量降低。


 

  然后,谈谈配置autofac。

  这里,发现这工具很好,很强大,至于有多强大,我也不清楚,因为我也很菜(/ □ \)……

  autofac配置园里相关文章也很多,我这里就初略的说说。

  First step:nuget上加入我们autofac的程序集引用:

  多層架構+MVC+EF+AUTOFAC+AUTOMAPPER

  注意,根据你所使用的.net环境选择相应的程序集,目前最新的版本是3.1.0,低版本的autofac是不支持.net4.0的。我们这里使用了MVC4.0所以选择第二个。

  Second step:配置依赖注入,说白了就是告诉autofac你要将哪个类与接口“发生关系”。

  多層架構+MVC+EF+AUTOFAC+AUTOMAPPER

  在这个框架中,我们将配置信息在图示类中完成:

  

多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
namespace YTJWGL_WebUI.RegisterAutofac
{
    public static class RegisterAutofacForSingle
    {
        public static void RegisterAutofac()
        {
            ContainerBuilder builder = new ContainerBuilder();
            builder.RegisterControllers(Assembly.GetExecutingAssembly());

            #region IOC注册区域
            //倘若需要默认注册所有的,请这样写(主要参数需要修改)
            //builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
            //   .AsImplementedInterfaces();
           
            //Admin
            builder.RegisterType<AdminService>().As<IAdminService>().InstancePerHttpRequest();

          
            #endregion
            // then
            var container = builder.Build();
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
          
        }

       
    }
}
RegisterAutofacForSingle

  autofac有很多重配置方式,详询此处:http://www.cnblogs.com/hkncd/archive/2012/11/28/2792474.html

  好了,下面我们在全局文件Global.asax中调用刚才定义的方法:

  

多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
 1 namespace YTJWGL_WebUI
 2 {
 3     // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
 4     // visit http://go.microsoft.com/?LinkId=9394801
 5     public class MvcApplication : System.Web.HttpApplication
 6     {
 7         protected void Application_Start()
 8         {
 9             AreaRegistration.RegisterAllAreas();
10 
11             WebApiConfig.Register(GlobalConfiguration.Configuration);
12             FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
13             RouteConfig.RegisterRoutes(RouteTable.Routes);
14 
15             //autofac注册
16             RegisterAutofacForSingle.RegisterAutofac();
17           
18 
19             //automapper注册
20             RegisterAutomapper.Excute();
21         }
22     }
23 }
Global.asax

  至此,autofac的配置就基本OK。其是用也比较的方便,autofac是使用构造函数注入:

  

多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
 1 namespace YTJWGL_WebUI.Areas.Admin.Controllers
 2 {
 3     
 4     public class FrameController : Controller
 5     {
 6         //
 7         // GET: /Admin/Frame/
 8         #region Fields
 9 
10         private readonly IAdminService _adminService;
11        
12         #endregion
13 
14         #region Constructors
15 
16         public FrameController(IAdminService adminService)
17         {
18             this._adminService = adminService;        
19         }
20         #endregion
21 
22         #region Admin
23 
24         [HttpPost]
25         public ActionResult Login(LoginModel model, string returnUrl)
26         {
27          //这样调用
28            var amin = _adminService.GetAllEntities(p => p.ID != 0);
29         }
30 
31     
32 
33        
34        
35       
36     }
37 }
FrameController

  这样就可以使用接口调用方法了。autofac简单配置完毕。


  接下来我们配置automapper:

  First Step:与autofac同样的方法在nuget里面安装。

  Secoud Step:

    多層架構+MVC+EF+AUTOFAC+AUTOMAPPER

  我把automapper分为两部配置,第一步与autofac类似,首先注册,也就是告诉automapper组件,你要在哪两个Model之间映射:

多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
 1 namespace YTJWGL_WebUI.Automapper
 2 {
 3     public static class RegisterAutomapper
 4     {
 5         public static void Excute()
 6         {
 7 
 8             //Admin
 9             Mapper.CreateMap<LoginModel, YTJWGL_Admin>();
10             Mapper.CreateMap<YTJWGL_Admin, LoginModel>().ForMember(dest => dest.ValidatorCode, sor => sor.Ignore());
11      
12         }
13 
14     }
15 }
多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
RegisterAutomapper

  代码中Formeber后面的代码可以不要,详情在这:http://www.cnblogs.com/ljzforever/archive/2011/12/29/2305500.html;

  然后看看我们第二个文件MapperExtention:

  

多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
 1 namespace YTJWGL_WebUI.Automapper
 2 {
 3     public static class MapperExtention
 4     {
 5         #region Admin
 6 
 7        public static AdminModel ToModel(this YTJWGL_Admin entity)
 8         {
 9             return Mapper.Map<YTJWGL_Admin, AdminModel>(entity);
10         }
11 
12         public static YTJWGL_Admin ToEntity(this AdminModel model)
13         {
14             return Mapper.Map<AdminModel, YTJWGL_Admin>(model);
15         }
16 
17         public static YTJWGL_Admin ToEntity(this AdminModel model, YTJWGL_Admin destination)
18         {
19             return Mapper.Map<AdminModel, YTJWGL_Admin>(model, destination);
20         }
21     
22     }
23 }
多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
MapperExtention

  MapperExtention中定义了一个个拓展方法,添加这个文件会让我们在控制器中映射实体变得非常方便:

  

多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
1  public ActionResult List()
2         {
3             //数据库实体向ViewModel转换
4             var model = _newsService.GetEntityByQuery(p => p.ID == 1).ToModel();
5             //ViewModel向数据库实体转换
6             var entity = model.ToEntity();
7             return View();
8         }
多層架構+MVC+EF+AUTOFAC+AUTOMAPPER
List

  就向调用ToString()方法一样的使用。

  当然,我们的automapper还需要在Global文件中调用,这一步在autofac最后一张图中已经说明。

  下一篇,准备写一个mvc中验证码实现。

更多相关文章
一周排行
  • 淺談jQuery中 wrap() wrapAll() 與 wrapInner()的差異
      本文结合W3School的文档,分析了jQuery中 wrap() wrapAll()
  • ObjectiveC語法之NSDictionary和NSMutableDictionary
    Java 有Map,可以把数据以键值对的形式储存起来,取值的时候通过key就可以直接拿到对 ...
  • Lamport Logical Clock 學習
    1,导论 ①如何在分布式环境下定义系统中所有事件的发生顺序?②分布式环境下多个进程竞争资源
  • 方法一:撤换到源代码模式下,通过代码更改id 方法二:      1.关闭VS2005:      2.删除目录 C:\Documents and Settings\Administrator\Local Setti ...
  • ref,函数形参变量的输入有两种方式:传值,传址.而ref则为传址. out,顾名思义,即输出.相当于一个函数可以有多个返回值,这是C#中特有的 params,在数组形参前面使用,可以赋多个值. enum,枚举是由程
  • 网上说用msfpayload 生成什么注入进程什么攻击后门,后边的注入进程是吓唬人的,就是一种进程隐藏技术不理解没关系(解释一下:进程注入是指将可恶意的可执行代码注入到一个已经运行的进程一般是合法系统进程,达到来隐藏 ...
  • 步骤: 1. 首先按通常做法配置好PHP5连接MS SQL Server PHP.ini 里面打开 extension=php_mssql.dll 选项 (就是把前面的 : 号去掉) 2. 下载正确版本的 ntwdb
  • #!/usr/bin/env xdg-open [Desktop Entry] Encoding=UTF-8 Version=1.0 Type=Application Terminal=false Name=Chee
  • 练习1:创建用户Oracle,所属附加组database和sql,ID号为3000, 家目录为/home/database groupadd database groupadd sql (先新建两个用户组,问:gro
  • nginx 域名跳转 Nginx跳转自动到www域名规则配置,如果设置使 mgcrazy.com域名在用户访问的时候自动跳转到 www.mgcrazy.com呢?在网上找了好多资料都没有一个完整能解决的!以下是我的解