从零开始,搭建博客系统MVC5+EF6搭建框架(1),EF Code frist、实现泛型数据仓储以及业务逻辑
前言
从上篇30岁找份程序员的工作(伪程序员的独白),文章开始,我说过我要用我自学的技术,来搭建一个博客系统,也希望大家给点意见,另外我很感谢博客园的各位朋友们,对我那篇算是自我阶段总结文章的评论,在里面能看出有很多种声音,有支持的我的朋友给我加油打气,有分享自己工作经历的朋友,有提出忠肯意见的朋友,有对记事本写代码吐槽的朋友,也有希望让我换个行业的,觉得我可能不适合这个行业朋友,不管怎样,我都接受,都是大家同行的一些忠告,谢谢大家。
首先我要在这里感谢很多博客园里面的大牛,写了很多系列,很多学习资料,让我受益很多,有机会找个时间,我会把我浏览器中收藏的资源都整理出来,分享给大家,其实我会的这些都是自己在博客园看到的文章、在某宝买的视频、QQ群里看群主的分享公开课学的,希望大家多提宝贵意见。
一、框架搭建
首先创建几个文件夹:
01Data用来放链接数据的EF以及创建表的类;
02Core存放数据仓储一些跟数据库链接实现数据操作的部分:
03Services 用于存放业务逻辑处理;
04Common用于放公共应用的工具之类;
05UI mvc页面展示的就放在这里 以及web相关的核心代码
其中除了Wchl.CRM.WebUI创建的是MVC5应用程序,其他的都是创建类库
二、创建数据库
1.创建一个空的EF code frist环境,输入的名字为WMBlogDB
2、选择空的Code Frist模型
3、创建一个models文件存放所有表的类,这里先创建一个用户信息表的类sysUserInfo
sysUserInfo类:
1 namespace Wchl.WMBlog.Model.Models 2 { 3 public class sysUserInfo 4 { 5 /// <summary> 6 /// 用户ID 7 /// </summary> 8 public int uID { get; set; } 9 /// <summary> 10 /// 登录账号 11 /// </summary> 12 public string uLoginName { get; set; } 13 /// <summary> 14 /// 登录密码 15 /// </summary> 16 public string uLoginPWD { get; set; } 17 /// <summary> 18 /// 真实姓名 19 /// </summary> 20 public string uRealName { get; set; } 21 /// <summary> 22 /// 状态 23 /// </summary> 24 public int uStatus { get; set; } 25 /// <summary> 26 /// 备注 27 /// </summary> 28 public string uRemark { get; set; } 29 /// <summary> 30 /// 创建时间 31 /// </summary> 32 public System.DateTime uCreateTime { get; set; } 33 /// <summary> 34 /// 更新时间 35 /// </summary> 36 public System.DateTime uUpdateTime { get; set; } 37 } 38 }
4、创建一个maps文件夹,主要是用来放对表字段进行约束的类sysUserInfoMap
sysUserInfoMap类:
1 namespace Wchl.WMBlog.Model.Maps 2 { 3 public class sysUserInfoMap:EntityTypeConfiguration<sysUserInfo> 4 { 5 public sysUserInfoMap() 6 { 7 this.HasKey(u => u.uID); 8 this.Property(u => u.uLoginName).HasMaxLength(60); 9 this.Property(u => u.uLoginPWD).HasMaxLength(60); 10 this.Property(u => u.uRealName).HasMaxLength(60); 11 } 12 } 13 }
关于EntityTypeConfiguration类的用法,大家可以去看看博客园里面一些介绍文章,HasKey设置主键,HasMaxLength字段最大长度。
5、在控制台中创建数据库脚本 Enable-Migrations
6、修改Configuration类配置
7、在WMBlogDB类中重写OnModelCreating方法
重写OnModelCreating方法:
1 protected override void OnModelCreating(DbModelBuilder modelBuilder) 2 { 3 //移除表名为复数 4 modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 5 //自动添加实现EntityTypeConfiguration的类 6 modelBuilder.Configurations.AddFromAssembly(Assembly.GetExecutingAssembly()); 7 base.OnModelCreating(modelBuilder); 8 }
二、仓储层建设
1、在Wchl.WMBlog.IRepository中创建一个类,做为操作数据的父接口IBaseRepository,这里使用泛型来创建
IBaseRepository接口
1 namespace Wchl.WMBlog.IRepository.Base 2 { 3 public interface IBaseRepository<TEntity> where TEntity:class 4 { 5 #region 查询 6 /// <summary> 7 /// 单表查询 8 /// </summary> 9 /// <param name="predicate"></param> 10 /// <returns></returns> 11 List<TEntity> QueryWhere(Expression<Func<TEntity, bool>> predicate); 12 13 /// <summary> 14 /// 多表关联查询 15 /// </summary> 16 /// <param name="predicate"></param> 17 /// <param name="tableNames"></param> 18 /// <returns></returns> 19 List<TEntity> QueryJoin(Expression<Func<TEntity, bool>> predicate, string[] tableNames); 20 /// <summary> 21 /// 升序查询还是降序查询 22 /// </summary> 23 /// <typeparam name="TKey"></typeparam> 24 /// <param name="predicate"></param> 25 /// <param name="keySelector"></param> 26 /// <param name="IsQueryOrderBy"></param> 27 /// <returns></returns> 28 List<TEntity> QueryOrderBy<TKey>(Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, TKey>> keySelector, bool IsQueryOrderBy); 29 30 /// <summary> 31 /// 升序分页查询还是降序分页 32 /// </summary> 33 /// <typeparam name="TKey"></typeparam> 34 /// <param name="pageIndex">第几页</param> 35 /// <param name="pagesize">一页多少条</param> 36 /// <param name="rowcount">返回共多少条</param> 37 /// <param name="predicate">查询条件</param> 38 /// <param name="keySelector">排序字段</param> 39 /// <param name="IsQueryOrderBy">true为升序 false为降序</param> 40 /// <returns></returns> 41 List<TEntity> QueryByPage<TKey>(int pageIndex, int pagesize, out int rowcount, Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, TKey>> keySelector, bool IsQueryOrderBy); 42 #endregion 43 44 #region 编辑 45 /// <summary> 46 /// 通过传入的model加需要修改的字段来更改数据 47 /// </summary> 48 /// <param name="model"></param> 49 /// <param name="propertys"></param> 50 void Edit(TEntity model, string[] propertys); 51 52 /// <summary> 53 /// 直接查询之后再修改 54 /// </summary> 55 /// <param name="model"></param> 56 void Edit(TEntity model); 57 #endregion 58 59 #region 删除 60 void Delete(TEntity model, bool isadded); 61 #endregion 62 63 #region 新增 64 void Add(TEntity model); 65 #endregion 66 67 #region 统一提交 68 int SaverChanges(); 69 #endregion 70 71 #region 调用存储过程返回一个指定的TResult 72 List<TResult> RunProc<TResult>(string sql, params object[] pamrs); 73 #endregion 74 } 75 }
2、然后实现IBaseRepository接口,在Wchl.WMBlog.Repository程序集中创建BaseRepository类来实现对数据操作的查询、增加、删除、编辑等。
BaseRepository类
1 namespace Wchl.WMBlog.Repository.Base 2 { 3 public class BaseRepository<TEntity>: IBaseRepository<TEntity> where TEntity:class 4 { 5 WMBlogDB db = new WMBlogDB(); 6 7 DbSet<TEntity> _dbSet; 8 9 public BaseRepository() 10 { 11 _dbSet = db.Set<TEntity>(); 12 } 13 14 #region 查询 15 /// <summary> 16 /// 单表查询 17 /// </summary> 18 /// <param name="predicate"></param> 19 /// <returns></returns> 20 public List<TEntity> QueryWhere(Expression<Func<TEntity, bool>> predicate) 21 { 22 return _dbSet.Where(predicate).ToList(); 23 } 24 25 /// <summary> 26 /// 多表关联查询 27 /// </summary> 28 /// <param name="predicate"></param> 29 /// <param name="tableNames"></param> 30 /// <returns></returns> 31 public List<TEntity> QueryJoin(Expression<Func<TEntity, bool>> predicate, string[] tableNames) 32 { 33 if (tableNames == null && tableNames.Any() == false) 34 { 35 throw new Exception("缺少连表名称"); 36 } 37 38 DbQuery<TEntity> query = _dbSet; 39 40 foreach (var table in tableNames) 41 { 42 query = query.Include(table); 43 } 44 45 return query.Where(predicate).ToList(); 46 } 47 48 /// <summary> 49 /// 升序查询还是降序查询 50 /// </summary> 51 /// <typeparam name="TKey"></typeparam> 52 /// <param name="predicate"></param> 53 /// <param name="keySelector"></param> 54 /// <param name="IsQueryOrderBy"></param> 55 /// <returns></returns> 56 public List<TEntity> QueryOrderBy<TKey>(Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, TKey>> keySelector,bool IsQueryOrderBy) 57 { 58 if (IsQueryOrderBy) 59 { 60 return _dbSet.Where(predicate).OrderBy(keySelector).ToList(); 61 } 62 return _dbSet.Where(predicate).OrderByDescending(keySelector).ToList(); 63 64 } 65 66 /// <summary> 67 /// 升序分页查询还是降序分页 68 /// </summary> 69 /// <typeparam name="TKey"></typeparam> 70 /// <param name="pageIndex">第几页</param> 71 /// <param name="pagesize">一页多少条</param> 72 /// <param name="rowcount">返回共多少条</param> 73 /// <param name="predicate">查询条件</param> 74 /// <param name="keySelector">排序字段</param> 75 /// <param name="IsQueryOrderBy">true为升序 false为降序</param> 76 /// <returns></returns> 77 public List<TEntity> QueryByPage<TKey>(int pageIndex,int pagesize,out int rowcount,Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, TKey>> keySelector, bool IsQueryOrderBy) 78 { 79 rowcount = _dbSet.Count(predicate); 80 if (IsQueryOrderBy) 81 { 82 return _dbSet.Where(predicate).OrderBy(keySelector).Skip((pageIndex - 1) * pagesize).Take(pagesize).ToList(); 83 } 84 else 85 { 86 return _dbSet.Where(predicate).OrderByDescending(keySelector).Skip((pageIndex - 1) * pagesize).Take(pagesize).ToList(); 87 } 88 } 89 #endregion 90 91 #region 编辑 92 /// <summary> 93 /// 通过传入的model加需要修改的字段来更改数据 94 /// </summary> 95 /// <param name="model"></param> 96 /// <param name="propertys"></param> 97 public void Edit(TEntity model, string[] propertys) 98 { 99 if (model == null) 100 { 101 throw new Exception("实体不能为空"); 102 } 103 104 if (propertys.Any() == false) 105 { 106 throw new Exception("要修改的属性至少要有一个"); 107 } 108 109 //将model追击到EF容器 110 DbEntityEntry entry = db.Entry(model); 111 112 entry.State = EntityState.Unchanged; 113 114 foreach (var item in propertys) 115 { 116 entry.Property(item).IsModified = true; 117 } 118 119 //关闭EF对于实体的合法性验证参数 120 db.Configuration.ValidateOnSaveEnabled = false; 121 } 122 123 /// <summary> 124 /// 直接查询之后再修改 125 /// </summary> 126 /// <param name="model"></param> 127 public void Edit(TEntity model) 128 { 129 db.Entry(model).State = EntityState.Modified; 130 } 131 #endregion 132 133 #region 删除 134 public void Delete(TEntity model, bool isadded) 135 { 136 if (!isadded) { 137 _dbSet.Attach(model); 138 } 139 _dbSet.Remove(model); 140 } 141 #endregion 142 143 #region 新增 144 public void Add(TEntity model) 145 { 146 _dbSet.Add(model); 147 } 148 #endregion 149 150 #region 统一提交 151 public int SaverChanges() 152 { 153 return db.SaveChanges(); 154 } 155 #endregion 156 157 #region 调用存储过程返回一个指定的TResult 158 public List<TResult> RunProc<TResult>(string sql, params object[] pamrs) 159 { 160 return db.Database.SqlQuery<TResult>(sql, pamrs).ToList(); 161 } 162 #endregion 163 } 164 }
三、业务逻辑层父接口和父类创建
1、在Wchl.WMBlog.IServices程序集中创建IBaseServices接口
IBaseServices接口:
1 namespace Wchl.WMBlog.IServices.Base 2 { 3 public interface IBaseServices<TEntity> where TEntity:class 4 { 5 #region 查询 6 /// <summary> 7 /// 单表查询 8 /// </summary> 9 /// <param name="predicate"></param> 10 /// <returns></returns> 11 List<TEntity> QueryWhere(Expression<Func<TEntity, bool>> predicate); 12 13 /// <summary> 14 /// 多表关联查询 15 /// </summary> 16 /// <param name="predicate"></param> 17 /// <param name="tableNames"></param> 18 /// <returns></returns> 19 List<TEntity> QueryJoin(Expression<Func<TEntity, bool>> predicate, string[] tableNames); 20 /// <summary> 21 /// 升序查询还是降序查询 22 /// </summary> 23 /// <typeparam name="TKey"></typeparam> 24 /// <param name="predicate"></param> 25 /// <param name="keySelector"></param> 26 /// <param name="IsQueryOrderBy"></param> 27 /// <returns></returns> 28 List<TEntity> QueryOrderBy<TKey>(Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, TKey>> keySelector, bool IsQueryOrderBy); 29 30 /// <summary> 31 /// 升序分页查询还是降序分页 32 /// </summary> 33 /// <typeparam name="TKey"></typeparam> 34 /// <param name="pageIndex">第几页</param> 35 /// <param name="pagesize">一页多少条</param> 36 /// <param name="rowcount">返回共多少条</param> 37 /// <param name="predicate">查询条件</param> 38 /// <param name="keySelector">排序字段</param> 39 /// <param name="IsQueryOrderBy">true为升序 false为降序</param> 40 /// <returns></returns> 41 List<TEntity> QueryByPage<TKey>(int pageIndex, int pagesize, out int rowcount, Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, TKey>> keySelector, bool IsQueryOrderBy); 42 #endregion 43 44 #region 编辑 45 /// <summary> 46 /// 通过传入的model加需要修改的字段来更改数据 47 /// </summary> 48 /// <param name="model"></param> 49 /// <param name="propertys"></param> 50 void Edit(TEntity model, string[] propertys); 51 52 /// <summary> 53 /// 直接查询之后再修改 54 /// </summary> 55 /// <param name="model"></param> 56 void Edit(TEntity model); 57 #endregion 58 59 #region 删除 60 void Delete(TEntity model, bool isadded); 61 #endregion 62 63 #region 新增 64 void Add(TEntity model); 65 #endregion 66 67 #region 统一提交 68 int SaverChanges(); 69 #endregion 70 71 #region 调用存储过程返回一个指定的TResult 72 List<TResult> RunProc<TResult>(string sql, params object[] pamrs); 73 #endregion 74 } 75 }
2、在Wchl.WMBlog.Services程序集创建BaseServices类
BaseServices类
1 namespace Wchl.WMBlog.Services.Base 2 { 3 public class BaseServices<TEntity>: IBaseServices<TEntity> where TEntity:class 4 { 5 public IBaseRepository<TEntity> baseDal = new BaseRepository<TEntity>(); 6 7 #region 查询 8 /// <summary> 9 /// 单表查询 10 /// </summary> 11 /// <param name="predicate"></param> 12 /// <returns></returns> 13 public List<TEntity> QueryWhere(Expression<Func<TEntity, bool>> predicate) 14 { 15 return baseDal.QueryWhere(predicate); 16 } 17 18 /// <summary> 19 /// 多表关联查询 20 /// </summary> 21 /// <param name="predicate"></param> 22 /// <param name="tableNames"></param> 23 /// <returns></returns> 24 public List<TEntity> QueryJoin(Expression<Func<TEntity, bool>> predicate, string[] tableNames) 25 { 26 return baseDal.QueryJoin(predicate, tableNames); 27 28 } 29 30 /// <summary> 31 /// 升序查询还是降序查询 32 /// </summary> 33 /// <typeparam name="TKey"></typeparam> 34 /// <param name="predicate"></param> 35 /// <param name="keySelector"></param> 36 /// <param name="IsQueryOrderBy"></param> 37 /// <returns></returns> 38 public List<TEntity> QueryOrderBy<TKey>(Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, TKey>> keySelector, bool IsQueryOrderBy) 39 { 40 return baseDal.QueryOrderBy(predicate, keySelector, IsQueryOrderBy); 41 } 42 43 /// <summary> 44 /// 升序分页查询还是降序分页 45 /// </summary> 46 /// <typeparam name="TKey"></typeparam> 47 /// <param name="pageIndex">第几页</param> 48 /// <param name="pagesize">一页多少条</param> 49 /// <param name="rowcount">返回共多少条</param> 50 /// <param name="predicate">查询条件</param> 51 /// <param name="keySelector">排序字段</param> 52 /// <param name="IsQueryOrderBy">true为升序 false为降序</param> 53 /// <returns></returns> 54 public List<TEntity> QueryByPage<TKey>(int pageIndex, int pagesize, out int rowcount, Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, TKey>> keySelector, bool IsQueryOrderBy) 55 { 56 57 return baseDal.QueryByPage(pageIndex, pagesize,out rowcount, predicate, keySelector, IsQueryOrderBy); 58 59 } 60 #endregion 61 62 #region 编辑 63 /// <summary> 64 /// 通过传入的model加需要修改的字段来更改数据 65 /// </summary> 66 /// <param name="model"></param> 67 /// <param name="propertys"></param> 68 public void Edit(TEntity model, string[] propertys) 69 { 70 baseDal.Edit(model, propertys); 71 } 72 73 /// <summary> 74 /// 直接查询之后再修改 75 /// </summary> 76 /// <param name="model"></param> 77 public void Edit(TEntity model) 78 { 79 baseDal.Edit(model); 80 } 81 #endregion 82 83 #region 删除 84 public void Delete(TEntity model, bool isadded) 85 { 86 baseDal.Delete(model, isadded); 87 } 88 #endregion 89 90 #region 新增 91 public void Add(TEntity model) 92 { 93 baseDal.Add(model); 94 } 95 #endregion 96 97 #region 统一提交 98 public int SaverChanges() 99 { 100 return baseDal.SaverChanges(); 101 } 102 #endregion 103 104 #region 调用存储过程返回一个指定的TResult 105 public List<TResult> RunProc<TResult>(string sql, params object[] pamrs) 106 { 107 return baseDal.RunProc<TResult>(sql, pamrs); 108 } 109 #endregion 110 } 111 }
到目前为止数据库、仓储层、业务逻辑层的父类和父接口都实现了,下一篇博文就在UI层怎么调用,测试看,成功写成功没。
谢谢大家的支持,多提宝贵意见。