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


一、目录

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

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

二、正文

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

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

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

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

class="code_img_closed" src="/Upload/Images/2013113016/0015B68B3C38AA5B.gif" alt="" />logs_code_hide('04dfa4e5-5ea4-401d-8696-ca7511b37b40',event)" src="/Upload/Images/2013113016/2B1B950FA3DF188F.gif" alt="" />

 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 }

IDAO

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

  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>
111 /// <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层文件:

1 namespace YTJWGL_IDao
2 {
3 public interface IAdminDao<T> : IBaseDao<T> where T : class
4 {
5
6 }
7 }

IAdminDao

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的程序集引用:

  

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

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

  

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

  

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中调用刚才定义的方法:

  

 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是使用构造函数注入:

  

 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:

   

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

 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 }

RegisterAutomapper

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

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

  

 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 }

MapperExtention

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

  

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 }

List

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

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

多层架构+MVC+EF+AUTOFAC+AUTOMAPPER的更多相关文章

  1. 使用.Net Core Mvc +SqlSugar +Autofac+AutoMapper+....

    开源地址:https://github.com/AjuPrince/Aju.Carefree 目前用到了 SqlSugar.Dapper.Autofac.AutoMapper.Swagger.Redi ...

  2. 分享一个MVC的多层架构,欢迎大家拍砖斧正

    如果你对项目管理.系统架构有兴趣,请加微信订阅号"softjg",加入这个PM.架构师的大家庭 多层架构是开发人员在开发过程当中面对复杂且易变的需求采取的一种以隔离控制为主的应对策 ...

  3. 转载Mvc的多层架构

    Mvc的多层架构 分享一个Mvc的多层架构,欢迎大家拍砖斧正   多层架构是什么? 多层架构是开发人员在开发过程当中面对复杂且易变的需求采取的一种以隔离控制为主的应对策略,关于多层架构的标准,我认为有 ...

  4. Mvc的多层架构

    分享一个Mvc的多层架构,欢迎大家拍砖斧正   多层架构是什么? 多层架构是开发人员在开发过程当中面对复杂且易变的需求采取的一种以隔离控制为主的应对策略,关于多层架构的标准,我认为有一句话是比较有代表 ...

  5. ASP.Net MVC+EF架构

    ASP.Net MVC是UI层的框架,EF是数据访问的逻辑. 如果在Controller中using DbContext,把查询的结果的对象放到cshtml中显示,那么一旦在cshtml中访问关联属性 ...

  6. IoC~MVC3+EF+Autofac实现松耦合的系统架构

    MVC3+EF+Autofac网上这种文章确实没有,呵呵,今天就写一个,代大家分享! 这个系列的文章将带我们进入一种新的开发模式,注入开发模式,或者叫它IOC模式,说起IOC你可以这样去理解它,它为你 ...

  7. 转载——Asp.Net MVC+EF+三层架构的完整搭建过程

    转载http://www.cnblogs.com/zzqvq/p/5816091.html Asp.Net MVC+EF+三层架构的完整搭建过程 架构图: 使用的数据库: 一张公司的员工信息表,测试数 ...

  8. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(16)-类库架构扩展以及DLL文件生成修改和用户的简单添加

    原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(16)-类库架构扩展以及DLL文件生成修改和用户的简单添加 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇) ...

  9. MVC 5 Scaffolding多层架构代码生成向导开源项目

    asp.net MVC 5 Scaffolding多层架构代码生成向导开源项目(邀请你的参与)   Visual Studio.net 2013 asp.net MVC 5 Scaffolding代码 ...

随机推荐

  1. echarts的使用

    ECharts是一个图形展示控件,基于javascript开发出来的,挺好用的,研究了下. 主页地址:http://echarts.baidu.com/index.html API地址:http:// ...

  2. PHP实现动态生成饼状图 (转载)

    <?php //变量定义,画椭圆弧时的角度大小 define("ANGLELENGTH", 10); /** * 绘制图片 * @param $title 3D图的标题 * ...

  3. Codeforces 301_div.2_Ice Cave(BFS走冰块)

    Ice Cave Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Descripti ...

  4. MVC中的过滤器

    authour: chenboyi updatetime: 2015-05-09 09:30:30 friendly link:   目录: 1,思维导图   2,过滤器种类(图示) 3,全局过滤器 ...

  5. bzoj2534: Uva10829L-gap字符串

    Description 有一种形如uvu形式的字符串,其中u是非空字符串,且V的长度正好为L,那么称这个字符串为L-Gap字符串 给出一个字符串S,以及一个正整数L,问S中有多少个L-Gap子串. I ...

  6. IT的发展路径

    1.掌握更多的技能 2.掌握某一门深入的技能 3.掌握更多的工具 4.掌握业务

  7. Ansible二三事

    现在,慢慢测试一下ANSIBLE的功能,不过,总体感觉是,比SALTSTACK运行要慢,好像还有点点不稳定.... 但,在局域环境的表现,还是不错的... ~~~~~~~~~~~~~ 有几个小事要注意 ...

  8. C语言---递归反向输出任意长度的字符串

    (该字符串可以包含空格和回车!) [题目要求] 编写一个递归函数,实现将输入的任意长度的字符串反向输出的功能. 例如输入字符串:ABCD,输出字符串:DCBA. [题目分析] 应用递归的思想有时可以很 ...

  9. [Design Pattern] Command Pattern 命令模式

    发现公司的代码好像有用到 Command Pattern,回顾重温下. Command Pattern 的类图结构如下: 参考 <Head First Design Patterns(英文版)& ...

  10. mybatis使用时org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):的错误

    最近在使用mybatis时,出现了 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): 这 ...