MVC项目搭建笔记----
项目框架采用ASP.NET MVC+Entity Framwork+Spring.Net等技术搭建,采用”Domain Model as View Model“的MVC开发模式,结合了抽象工厂的思想降低了三层之间的耦合,可以使用此套框架进行MVC项目的快速搭建。本框架的架构图如下:
第一步(创建分类文件夹):
创建5个文件夹。分别为UI,Model,BLL,DAL,Common,以便于将各模块分类整理。
第二步(项目类库的创建):
在UI文件夹创建ASP.NET MVC4项目模板选择基本。
在Model文件夹创建Model类库项目。
在BLL文件夹创建BLL和IBLL类库项目。
在DAL文件夹创建DAL,IDAL,DALFactory类库项目。
在Common文件夹创建Common类库项目。
第三步(创建EF实体):
在数据库管理工具新建一个数据库,在Model层添加一个ADO.Net实体模型。
建好实体模型,右键选择“根据模型生成数据库”,也可以先建好数据库再右键“从数据库更新模型”。
第四步(各层内容的创建,重点!):
在DAL层创建一个EFDbContextFactory类。(CallContext是类似于方法调用的线程本地存储区的专用集合对象,并提供对每个逻辑执行线程都唯一的数据槽。数据槽不在其他逻辑线程上的调用上下文之间共享。)
1 public class EFDbContextFactory 2 { 3 public static DbContext GetCurrentDbContext() 4 { 5 //线程内的单例:保证线程内实例唯一 6 DbContext db = (DbContext)CallContext.GetData("DbContext"); 7 if (db == null) 8 { 9 db = new Model1Container(); 10 11 CallContext.SetData("DbContext", db); 12 } 13 return db; 14 } 15 }
在DAL层创建一个BaseDal类,作为所有Dal的基类,封装crud方法。
1 public class BaseDalwhere T : class , new() 2 { 3 private DbContext db 4 { 5 get 6 { 7 return EFDbContextFactory.GetCurrentDbContext(); 8 } 9 } 10 public virtual T Add(T entity) 11 { 12 db.Set ().Add(entity); 13 return entity; 14 } 15 16 public virtual bool Update(T entity) 17 { 18 db.Entry(entity).State = EntityState.Modified; 19 return true; 20 } 21 22 public virtual bool Delete(T entity) 23 { 24 db.Entry(entity).State = EntityState.Deleted; 25 return true; 26 27 } 28 29 public virtual int Delete(params int[] ids) 30 { 31 foreach (var item in ids) 32 { 33 var entity = db.Set ().Find(item);//如果实体已经在内存中,那么就直接从内存拿,如果内存中跟踪实体没有,那么才查询数据库。 34 db.Set ().Remove(entity); 35 } 36 return ids.Count(); 37 } 38 39 public List LoadEntities(Expression bool>> whereLambda) 40 { 41 return db.Set ().Where(whereLambda).AsQueryable(); 42 } 43 44 public List LoadPageEntities (int pageSize, int pageIndex, out int total, Expressionbool>> whereLambda, Expression > orderbyLambda, bool isAsc) 45 { 46 total = db.Set ().Where(whereLambda).Count(); 47 if (isAsc) 48 { 49 return 50 db.Set () 51 .Where(whereLambda) 52 .OrderBy(orderbyLambda) 53 .Skip(pageSize * (pageIndex - 1)) 54 .Take(pageSize) 55 .AsQueryable().ToList(); 56 } 57 else 58 { 59 return 60 db.Set () 61 .Where(whereLambda) 62 .OrderByDescending(orderbyLambda) 63 .Skip(pageSize * (pageIndex - 1)) 64 .Take(pageSize) 65 .AsQueryable().ToList(); 66 } 67 } 68 } 69
在DAL层添加Dal类的T4模板(Dal类生成模板,生成各Dal类,包括继承类和接口,未给出,可自行编写)。T4模板生成的Dal类内容模板如下:
1 public partial class UserInfoDal : BaseDal,IUserInfoDal 2 { 3 4 }
在IDAL层添加IDal接口类的T4模板(未给出,自行编写)。T4模板生成的IDal类内容模板如下:
1 public partial interface IUserInfoDal :IBaseDal2 { 3 4 }
在IDAL层添加IBaseDal接口类,作为IDal的基接口类,子接口只要继承此接口就可以实现crud(增删改查)及分页接口。
1 public interface IBaseDal2 { 3 T Add(T entity); 4 bool Update(T entity); 5 bool Delete(T entity); 6 int Delete(params int[] ids); 7 List LoadEntities(Expression bool>> whereLambda); 8 List LoadPageEntities (int pageSize, int pageIndex, out int total, Expressionbool>> whereLambda, Expression > orderbyLambda, bool isAsc); 9 }
在IDAL层添加IDbSession接口类(此类作为DbSession类的约束,符合抽象的思想,不直接返回对象本身,而是返回他的接口,这样就不会直接对对象本身造成依赖,只要修改IDbSession)的T4模板(未给出,自行编写)。T4模板生成的IDbSession类内容模板如下:
1 public partial interface IDbSession 2 { 3 IUserInfoDal UserInfoDal { get; } 4 int SaveChanges(); 5 }
在DALFactory层添加DbSession类的T4模板(未给出,自行编写)。T4模板生成的DbSession类内容模板如下:
1 public partial class DbSession :IDbSession 2 { 3 4 private IUserInfoDal _UserInfoDal; 5 public IUserInfoDal UserInfoDal { 6 get { 7 if (_UserInfoDal == null) 8 { 9 _UserInfoDal =new UserInfoDal(); 10 } 11 return _UserInfoDal; 12 } 13 } 14 15 public int SaveChanges() 16 { 17 //这里只需要调用当前线程内部的上下文SaveChange。 18 DbContext dbContext = EFDbContextFactory.GetCurrentDbContext(); 19 return dbContext.SaveChanges(); 20 } 21 }
在DALFactory层添加DbSessionFactory类,作为dbSession的工厂。
1 public class DbSessionFactory 2 { 3 public static IDbSession GetDbSession() 4 { 5 IDbSession dbSession = (IDbSession) CallContext.GetData("DbSession"); 6 if (dbSession == null) 7 { 8 dbSession = new DbSession(); 9 CallContext.SetData("DbSession", dbSession); 10 return dbSession; 11 } 12 return dbSession; 13 } 14 }
在IBLL层创建IBaseService基接口类,作为所有IService接口类的crud公共约束。
1 public interface IBaseService2 { 3 T Add(T entity); 4 bool Update(T entity); 5 bool Delete(T entity); 6 int Delete(params int[] ids); 7 List LoadEntities(Expression bool>> whereLambda); 8 9 List LoadPageEntities (int pageSize, int pageIndex, out int total, 10 Expressionbool>> whereLambda 11 , Expression > orderbyLambda, bool isAsc); 12 int Savechanges(); 13 }
在IBLL层添加IBLL接口类的T4模板(未给出,自行编写)。T4模板生成的IBLL接口类内容模板如下:
1 public partial interface IUserInfoService :IBaseService2 { 3 4 }
在BLL层创建BaseService类(作为所有Service类的基类,封装crud方法)。
1 public abstract class BaseServicewhere T:class,new () 2 { 3 public IDbSession DbSession 4 { 5 get { return DbSessionFactory.GetDbSession(); } 6 } 7 8 public IBaseDal CurrentDal; 9 10 public int Savechanges() 11 { 12 return DbSession.SaveChanges(); 13 } 14 15 //要求所有的业务方法在执行之前必须给当前的CurrentDal 赋值。 16 public BaseService() 17 { 18 SetCurrentDal(); 19 } 20 21 //纯抽象方法:子类必须重写此方法。 22 public abstract void SetCurrentDal(); 23 24 public virtual T Add(T entity) 25 { 26 return CurrentDal.Add(entity); 27 } 28 29 public virtual bool Update(T entity) 30 { 31 CurrentDal.Update(entity); 32 33 return this.Savechanges() > 0; 34 } 35 36 public virtual bool Delete(T entity) 37 { 38 return CurrentDal.Delete(entity); 39 40 } 41 42 public virtual int Delete(params int[] ids) 43 { 44 return CurrentDal.Delete(ids); 45 46 } 47 48 public List LoadEntities(Expression bool>> whereLambda) 49 { 50 return CurrentDal.LoadEntities(whereLambda); 51 52 } 53 54 public List LoadPageEntities (int pageSize, int pageIndex, out int total, Expressionbool>> whereLambda, Expression > orderbyLambda, bool isAsc) 55 { 56 return CurrentDal.LoadPageEntities(pageSize, pageIndex, out total, whereLambda, orderbyLambda, isAsc); 57 } 58 }
在BLL层添加Services类的T4模板(未给出,自行编写)。T4模板生成的Service类内容模板如下:
1 public partial class UserInfoService:BaseService,IUserInfoService 2 { 3 public override void SetCurrentDal() 4 { 5 CurrentDal = DbSession.UserInfoDal;//对父类虚方法进行重写,以对Dal初始化。 6 } 7 }
第五步(配置Spring.Net框架):
在UI层添加lib文件夹(用于存放所有外部引用文件),将Spring.Net程序集文件夹放到lib文件夹下,UI层添加对Spring.Core,Spring.Web,Spring.Web.Extensions,Spring.Web.Mvc4程序集的引用。
在Global.asax文件里将MvcApplication类继承至SpringMvcApplication。
在Web.config文件里的
1 2 <sectionGroup name="spring"> 3 <section name="context" type="Spring.Context.Support.MvcContextHandler, Spring.Web.Mvc4"/> 4 <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /> 5 sectionGroup> 6
在Web.config文件里的
1 2 <spring> 3 4 <context> 5 6 7 8 9 <resource uri="assembly://MyOA_BLL/MyOA_BLL/ServiceXml.xml"/> 10 <resource uri="assembly://MyOA/MyOA/Controllers.xml"/> 11 12 context> 13 <objects xmlns="http://www.springframework.net"> 14 15 objects> 16 17 spring> 18
第六步(注入Service对象):
在BLL层添加生成ServiceXml配置文件的T4模板(Speing.Net属性注入方法请参见 http://www.cnblogs.com/sunniest/p/4125561.html ),内容模板为:
1 <objects xmlns="http://www.springframework.net"> 2 <object name="UserInfoService" type="MyOA_BLL.UserInfoService, MyOA_BLL" singleton="false"> 3 4 object> 5 6 objects>
在Controller文件夹下的各Controller类中添加
1 public IUserInfoService UserInfoService{get;set;} 2 IDbSession session = DbSessionFactory.GetDbSession();
用UserInfoService来调用业务逻辑的方法(通过Spring.net注入UserInfoService对象),在操作完成后用session的savechanges方法控制将对实体的操作保存到数据库中。
在UI层添加Controller.xml文件(用于向Controller类注入UserInfoService对象),内容模板为:
1 <objects xmlns="http://www.springframework.net"> 2 <object name="TestController" type="MyOA.Controllers.TestController, MyOA" singleton="false"> 3 <property name="UserInfoService" ref="UserInfoService" /> 4 object> 5 6 objects>
至此项目基本框架搭建完成!
Controller调用业务逻辑层完整代码示例:
1 public ActionResult Test() 2 { 3 return View(); 4 } 5 6 [HttpPost] 7 public ActionResult Test(string uname,string pwd) 8 { 9 UserInfo u =new UserInfo(); 10 u.UserName=uname; 11 u.Pwd=pwd; 12 var t = UserInfoService.Add(u); 13 session.SaveChanges(); 14 if(t.Id>0){ 15 return Content("注册成功!"); 16 } 17 else{ 18 return Content("注册失败!"); 19 } 20 }