.netCore+Vue 搭建的简捷开发框架 (2)--仓储层实现和EFCore 的使用
2019-08-28 13:26
381 查看
书接上文,继续搭建我们基于.netCore 的开发框架。首先是我们的项目分层结构。
using Sincere.Core.Model; using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; namespace Sincere.Core.IRepository.Base { public interface IBaseRepository<TEntity> where TEntity : class { Task<int> Execute(string sql, List<SqlParameter> parms, CommandType cmdType = CommandType.Text); Task<List<TEntity>> Query(string sql, List<SqlParameter> parms, CommandType cmdType = CommandType.Text); Task<bool> Insert(TEntity model); Task<bool> InsertRange(List<TEntity> datas); Task<int> Del(TEntity model); Task<int> DelBy(Expression<Func<TEntity, bool>> delWhere); Task<int> Modify(TEntity model); Task<int> Modify(TEntity model, params string[] propertyNames); Task<int> ModifyBy(TEntity model, Expression<Func<TEntity, bool>> whereLambda, params string[] modifiedPropertyNames); Task<List<TEntity>> GetList(); Task<List<TEntity>> GetListBy(Expression<Func<TEntity, bool>> whereLambda); Task<TEntity> GetModelById(Expression<Func<TEntity, bool>> whereLambda); Task<List<TEntity>> GetListBy<TKey>(Expression<Func<TEntity, bool>> whereLambda, Expression<Func<TEntity, TKey>> orderLambda, bool isAsc = true); Task<List<TEntity>> GetListBy<TKey>(int top, Expression<Func<TEntity, bool>> whereLambda, Expression<Func<TEntity, TKey>> orderLambda, bool isAsc = true); Task<List<TEntity>> GetListBy<TKey1, TKey2>(Expression<Func<TEntity, bool>> whereLambda, Expression<Func<TEntity, TKey1>> orderLambda1, Expression<Func<TEntity, TKey2>> orderLambda2, bool isAsc1 = true, bool isAsc2 = true); Task<List<TEntity>> GetListBy<TKey1, TKey2>(int top, Expression<Func<TEntity, bool>> whereLambda, Expression<Func<TEntity, TKey1>> orderLambda1, Expression<Func<TEntity, TKey2>> orderLambda2, bool isAsc1 = true, bool isAsc2 = true); Task<List<TEntity>> GetPagedList<TKey>(int pageIndex, int pageSize, Expression<Func<TEntity, bool>> whereLambda, Expression<Func<TEntity, TKey>> orderByLambda, bool isAsc = true); Task<PageModel<TEntity>> GetPagedList<TKey>(Expression<Func<TEntity, bool>> whereLambda, Expression<Func<TEntity, TKey>> orderByLambda, bool isAsc = true, int pageIndex = 1, int pageSize = 20); void RollBackChanges(); } }View Code BaseRepository.cs:
using Microsoft.EntityFrameworkCore; using Sincere.Core.IRepository.Base; using Sincere.Core.Model; using Sincere.Core.Model.Models; using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace Sincere.Core.Repository.Base { public class BaseRepository<TEntity> : IBaseRepository<TEntity> where TEntity : class, new() { private BaseCoreContext _db; private readonly DbSet<TEntity> _dbSet; internal BaseCoreContext Db { get { return _db; } private set { _db = value; } } public BaseRepository(IBaseContext mydbcontext) { this._db = mydbcontext as BaseCoreContext; this._dbSet = _db.Set<TEntity>(); } #region INSERT /// <summary> /// 新增 实体 /// </summary> /// <param name="model"></param> /// <returns></returns> //public async Task<bool> Insert(TEntity model, bool isSaveChanges = false) public async Task<bool> Insert(TEntity model) { _db.Set<TEntity>().Add(model); //if (isSaveChanges) //{ return await _db.SaveChangesAsync() > 0; //} //else //{ // return false; //} } /// <summary> /// 普通批量插入 /// </summary> /// <param name="datas"></param> public async Task<bool> InsertRange(List<TEntity> datas) { await _db.Set<TEntity>().AddRangeAsync(datas); return await _db.SaveChangesAsync() == datas.Count; } #endregion INSERT #region Delete #region 2.0 根据id删除 + int Del(T model) /// <summary> /// 2.0 根据id删除 /// </summary> /// <param name="model">必须包含要删除id的对象</param> /// <returns></returns> public async Task<int> Del(TEntity model) { _db.Set<TEntity>().Attach(model); _db.Set<TEntity>().Remove(model); return await _db.SaveChangesAsync(); } #endregion #region 2.1 根据条件删除 + int DelBy(Expression<Func<T, bool>> delWhere) /// <summary> /// 2.1 根据条件删除 /// </summary> /// <param name="delWhere"></param> /// <returns>返回受影响的行数</returns> public async Task<int> DelBy(Expression<Func<TEntity, bool>> delWhere) { //2.1.1 查询要删除的数据 List<TEntity> listDeleting = _db.Set<TEntity>().Where(delWhere).ToList(); //2.1.2 将要删除的数据 用删除方法添加到 EF 容器中 listDeleting.ForEach(u => { _db.Set<TEntity>().Attach(u); //先附加到EF 容器 _db.Set<TEntity>().Remove(u); //标识为删除状态 }); //2.1.3 一次性生成sql语句 到数据库执行删除 return await _db.SaveChangesAsync(); } #endregion #endregion #region UPDATE #region 3.0 修改实体 + int Modify(T model) /// <summary> /// 修改实体 /// </summary> /// <param name="model"></param> /// <returns></returns> public async Task<int> Modify(TEntity model) { //EntityEntry entry = _db.Entry<TEntity>(model); _db.Set<TEntity>().Update(model); return await _db.SaveChangesAsync(); } #endregion #region 3.1 修改实体,可修改指定属性 + int Modify(T model, params string[] propertyNames) /// <summary> /// 3.1 修改实体,可修改指定属性 /// </summary> /// <param name="model"></param> /// <param name="propertyName"></param> /// <returns></returns> public async Task<int> Modify(TEntity model, params string[] propertyNames) { //3.1.1 将对象添加到EF中 EntityEntry entry = _db.Entry<TEntity>(model); //3.1.2 先设置对象的包装状态为 Unchanged entry.State = EntityState.Unchanged; //3.1.3 循环被修改的属性名数组 foreach (string propertyName in propertyNames) { //将每个被修改的属性的状态设置为已修改状态;这样在后面生成的修改语句时,就只为标识为已修改的属性更新 entry.Property(propertyName).IsModified = true; } return await _db.SaveChangesAsync(); } #endregion #region 3.2 批量修改 + int ModifyBy(T model, Expression<Func<T, bool>> whereLambda, params string[] modifiedPropertyNames) /// <summary> /// 3.2 批量修改 /// </summary> /// <param name="model"></param> /// <param name="whereLambda"></param> /// <param name="modifiedPropertyNames"></param> /// <returns></returns> public async Task<int> ModifyBy(TEntity model, Expression<Func<TEntity, bool>> whereLambda, params string[] modifiedPropertyNames) { //3.2.1 查询要修改的数据 List<TEntity> listModifing = _db.Set<TEntity>().Where(whereLambda).ToList(); //3.2.2 获取实体类类型对象 Type t = typeof(TEntity); //3.2.3 获取实体类所有的公共属性 List<PropertyInfo> propertyInfos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList(); //3.2.4 创建实体属性字典集合 Dictionary<string, PropertyInfo> dicPropertys = new Dictionary<string, PropertyInfo>(); //3.2.5 将实体属性中要修改的属性名 添加到字典集合中 键:属性名 值:属性对象 propertyInfos.ForEach(p => { if (modifiedPropertyNames.Contains(p.Name)) { dicPropertys.Add(p.Name, p); } }); //3.2.6 循环要修改的属性名 foreach (string propertyName in modifiedPropertyNames) { //判断要修改的属性名是否在实体类的属性集合中存在 if (dicPropertys.ContainsKey(propertyName)) { //如果存在,则取出要修改的属性对象 PropertyInfo proInfo = dicPropertys[propertyName]; //取出要修改的值 object newValue = proInfo.GetValue(model, null); //批量设置要修改对象的属性 foreach (TEntity item in listModifing) { //为要修改的对象的要修改的属性设置新的值 proInfo.SetValue(item, newValue, null); } } } //一次性生成sql语句 到数据库执行 return await _db.SaveChangesAsync(); } #endregion #endregion UPDATE #region SELECT #region 5.0 根据条件查询 + List<TEntity> GetListBy(Expression<Func<T, bool>> whereLambda) /// <summary> /// 5.0 根据条件查询 /// </summary> /// <param name="whereLambda"></param> /// <returns></returns> public async Task<List<TEntity>> GetListBy(Expression<Func<TEntity, bool>> whereLambda) { return await _db.Set<TEntity>().Where(whereLambda).AsNoTracking().ToListAsync(); } public async Task<TEntity> GetModelById(Expression<Func<TEntity, bool>> whereLambda) { return await _db.Set<TEntity>().Where(whereLambda).AsNoTracking().FirstOrDefaultAsync(); } public async Task<List<TEntity>> GetList() { return await _db.Set<TEntity>().AsNoTracking().ToListAsync(); } #endregion #region 5.1 根据条件查询,并排序 + List<TEntity> GetListBy<TKey>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderLambda, bool isAsc = true) /// <summary> /// 5.1 根据条件查询,并排序 /// </summary> /// <typeparam name="TKey"></typeparam> /// <param name="whereLambda"></param> /// <param name="orderLambda"></param> /// <param name="isAsc"></param> /// <returns></returns> public async Task<List<TEntity>> GetListBy<TKey>(Expression<Func<TEntity, bool>> whereLambda, Expression<Func<TEntity, TKey>> orderLambda, bool isAsc = true) { if (isAsc) { return await _db.Set<TEntity>().Where(whereLambda).OrderBy(orderLambda).AsNoTracking().ToListAsync(); } else { return await _db.Set<TEntity>().Where(whereLambda).OrderByDescending(orderLambda).AsNoTracking().ToListAsync(); } } #endregion #region 5.2 根据条件查询Top多少个,并排序 + List<TEntity> GetListBy<TKey>(int top, Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderLambda, bool isAsc = true) /// <summary> /// 5.2 根据条件查询Top多少个,并排序 /// </summary> /// <typeparam name="TKey"></typeparam> /// <param name="top"></param> /// <param name="whereLambda"></param> /// <param name="orderLambda"></param> /// <param name="isAsc"></param> /// <returns></returns> public async Task<List<TEntity>> GetListBy<TKey>(int top, Expression<Func<TEntity, bool>> whereLambda, Expression<Func<TEntity, TKey>> orderLambda, bool isAsc = true) { if (isAsc) { return await _db.Set<TEntity>().Where(whereLambda).OrderBy(orderLambda).Take(top).AsNoTracking().ToListAsync(); } else { return await _db.Set<TEntity>().Where(whereLambda).OrderByDescending(orderLambda).Take(top).AsNoTracking().ToListAsync(); } } #endregion #region 5.3 根据条件排序查询 双排序 + List<TEntity> GetListBy<TKey1, TKey2>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey1>> orderLambda1, Expression<Func<T, TKey2>> orderLambda2, bool isAsc1 = true, bool isAsc2 = true) /// <summary> /// 5.3 根据条件排序查询 双排序 /// </summary> /// <typeparam name="TKey1"></typeparam> /// <typeparam name="TKey2"></typeparam> /// <param name="whereLambda"></param> /// <param name="orderLambda1"></param> /// <param name="orderLambda2"></param> /// <param name="isAsc1"></param> /// <param name="isAsc2"></param> /// <returns></returns> public async Task<List<TEntity>> GetListBy<TKey1, TKey2>(Expression<Func<TEntity, bool>> whereLambda, Expression<Func<TEntity, TKey1>> orderLambda1, Expression<Func<TEntity, TKey2>> orderLambda2, bool isAsc1 = true, bool isAsc2 = true) { if (isAsc1) { if (isAsc2) { return await _db.Set<TEntity>().Where(whereLambda).OrderBy(orderLambda1).ThenBy(orderLambda2).AsNoTracking().ToListAsync(); } else { return await _db.Set<TEntity>().Where(whereLambda).OrderBy(orderLambda1).ThenByDescending(orderLambda2).AsNoTracking().ToListAsync(); } } else { if (isAsc2) { return await _db.Set<TEntity>().Where(whereLambda).OrderByDescending(orderLambda1).ThenBy(orderLambda2).AsNoTracking().ToListAsync(); } else { return await _db.Set<TEntity>().Where(whereLambda).OrderByDescending(orderLambda1).ThenByDescending(orderLambda2).AsNoTracking().ToListAsync(); } } } #endregion #region 5.3 根据条件排序查询Top个数 双排序 + List<TEntity> GetListBy<TKey1, TKey2>(int top, Expression<Func<T, bool>> whereLambda, System.Linq.Expressions.Expression<Func<T, TKey1>> orderLambda1, Expression<Func<T, TKey2>> orderLambda2, bool isAsc1 = true, bool isAsc2 = true) /// <summary> /// 5.3 根据条件排序查询Top个数 双排序 /// </summary> /// <typeparam name="TKey1"></typeparam> /// <typeparam name="TKey2"></typeparam> /// <param name="top"></param> /// <param name="whereLambda"></param> /// <param name="orderLambda1"></param> /// <param name="orderLambda2"></param> /// <param name="isAsc1"></param> /// <param name="isAsc2"></param> /// <returns></returns> public async Task<List<TEntity>> GetListBy<TKey1, TKey2>(int top, Expression<Func<TEntity, bool>> whereLambda, Expression<Func<TEntity, TKey1>> orderLambda1, Expression<Func<TEntity, TKey2>> orderLambda2, bool isAsc1 = true, bool isAsc2 = true) { if (isAsc1) { if (isAsc2) { return await _db.Set<TEntity>().Where(whereLambda).OrderBy(orderLambda1).ThenBy(orderLambda2).Take(top).AsNoTracking().ToListAsync(); } else { return await _db.Set<TEntity>().Where(whereLambda).OrderBy(orderLambda1).ThenByDescending(orderLambda2).Take(top).AsNoTracking().ToListAsync(); } } else { if (isAsc2) { return await _db.Set<TEntity>().Where(whereLambda).OrderByDescending(orderLambda1).ThenBy(orderLambda2).Take(top).AsNoTracking().ToListAsync(); } else { return await _db.Set<TEntity>().Where(whereLambda).OrderByDescending(orderLambda1).ThenByDescending(orderLambda2).Take(top).AsNoTracking().ToListAsync(); } } } #endregion #endregion SELECT #region 分页 #region 6.0 分页查询 + List<T> GetPagedList<TKey> /// <summary> /// 分页查询 + List<TEntity> GetPagedList /// </summary> /// <typeparam name="TKey"></typeparam> /// <param name="pageIndex">页码</param> /// <param name="pageSize">页容量</param> /// <param name="whereLambda">条件 lambda表达式</param> /// <param name="orderBy">排序 lambda表达式</param> /// <returns></returns> public async Task<List<TEntity>> GetPagedList<TKey>(int pageIndex, int pageSize, Expression<Func<TEntity, bool>> whereLambda, Expression<Func<TEntity, TKey>> orderByLambda, bool isAsc = true) { // 分页 一定注意: Skip 之前一定要 OrderBy if (isAsc) { return await _db.Set<TEntity>().Where(whereLambda).OrderBy(orderByLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToListAsync(); } else { return await _db.Set<TEntity>().Where(whereLambda).OrderByDescending(orderByLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToListAsync(); } } #endregion #region 6.1分页查询 带输出 +List<TEntity> GetPagedList<TKey> /// <summary> /// 分页查询 带输出 /// </summary> /// <typeparam name="TKey"></typeparam> /// <param name="pageIndex"></param> /// <param name="pageSize"></param> /// <param name="rowCount"></param> /// <param name="whereLambda"></param> /// <param name="orderBy"></param> /// <param name="isAsc"></param> /// <returns></returns> public async Task<PageModel<TEntity>> GetPagedList<TKey>(Expression<Func<TEntity, bool>> whereLambda, Expression<Func<TEntity, TKey>> orderByLambda, bool isAsc = true, int pageIndex = 1, int pageSize = 20) { var rowCount = await _db.Set<TEntity>().Where(whereLambda).CountAsync(); int pageCount = (Math.Ceiling(rowCount.ObjToDecimal() / pageSize.ObjToDecimal())).ObjToInt(); List<TEntity> list = null; if (isAsc) { list = await _db.Set<TEntity>().OrderBy(orderByLambda).Where(whereLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToListAsync(); } else { list = await _db.Set<TEntity>().OrderByDescending(orderByLambda).Where(whereLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToListAsync(); } return new PageModel<TEntity>() { dataCount = rowCount, pageCount = pageCount, page = pageIndex, PageSize = pageSize, data = list }; } #endregion #endregion #region ORTHER /// <summary> /// 执行存储过程或自定义sql语句--返回集合 /// </summary> /// <param name="sql"></param> /// <param name="parms"></param> /// <param name="cmdType"></param> /// <returns></returns> public async Task<List<TEntity>> Query(string sql, List<SqlParameter> parms, CommandType cmdType = CommandType.Text) { //存储过程(exec getActionUrlId @name,@ID) if (cmdType == CommandType.StoredProcedure) { StringBuilder paraNames = new StringBuilder(); foreach (var sqlPara in parms) { paraNames.Append($" @{sqlPara},"); } sql = paraNames.Length > 0 ? $"exec {sql} {paraNames.ToString().Trim(',')}" : $"exec {sql} "; } return await _db.Set<TEntity>().FromSql(sql).ToListAsync(); } /// <summary> /// 回滚 /// </summary> public void RollBackChanges() { var items = _db.ChangeTracker.Entries().ToList(); items.ForEach(o => o.State = EntityState.Unchanged); } /// <summary> /// 自定义语句和存储过程的增删改--返回影响的行数 /// </summary> /// <param name="sql"></param> /// <param name="parms"></param> /// <param name="cmdType"></param> /// <returns></returns> public async Task<int> Execute(string sql, List<SqlParameter> parms, CommandType cmdType = CommandType.Text) { //存储过程(exec getActionUrlId @name,@ID) if (cmdType == CommandType.StoredProcedure) { StringBuilder paraNames = new StringBuilder(); foreach (var sqlPara in parms) { paraNames.Append($" @{sqlPara},"); } sql = paraNames.Length > 0 ? $"exec {sql} {paraNames.ToString().Trim(',')}" : $"exec {sql} "; } int ret = await _db.Database.ExecuteSqlCommandAsync(sql, parms.ToArray()); return 0; } #endregion ORTHER } }View Code
BaseRepository中主要是实现了一些基础的CURD操作,并且封装了一些常用的数据库操作。比如分页、执行sql语句等等
如果直接复制以上代码,会报错,因为你的项目中还没有数据上下文:
USE [BaseCore] GO /****** Object: Table [dbo].[Advertisement] Script Date: 08/28/2019 10:43:34 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[Advertisement]( [Id] [int] IDENTITY(1,1) NOT NULL, [Createdate] [datetime] NOT NULL, [ImgUrl] [nvarchar](512) NULL, [Title] [nvarchar](64) NULL, [Url] [nvarchar](256) NULL, [Remark] [nvarchar](max) NULL, CONSTRAINT [PK_dbo.Advertisement] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GOView Code
然后使用工具Scaffold-DbContext(数据库上下文脚手架)来生成model类文件和DbContext。
命令如下:
Scaffold-DbContext "server=.;database=XXX;uid=sa;pwd=密码;" Microsoft.EntityFrameworkCore.SqlServer -O Models -F -Context BaseCoreContext
在执行这个命令之前,需要将Model层设置为启动项目。否则会报错。
using System; using System.Collections.Generic; using System.Text; namespace Sincere.Core.Model { /// <summary> /// 通用分页信息类 /// </summary> public class PageModel<T> { /// <summary> /// 当前页标 /// </summary> public int page { get; set; } = 1; /// <summary> /// 总页数 /// </summary> public int pageCount { get; set; } = 6; /// <summary> /// 数据总数 /// </summary> public int dataCount { get; set; } = 0; /// <summary> /// 每页大小 /// </summary> public int PageSize { set; get; } /// <summary> /// 返回数据 /// </summary> public List<T> data { get; set; } } }View Code 另外里面还有一些 转换函数,请参考源码:https://github.com/xzhencheng/Sincere.Core.git
至此,项目的仓储层的基础代码就构建完了,今天的作业就先写到这!
相关文章推荐
- .netCore+Vue 搭建的简捷开发框架 (3)-- Services层实现
- .netCore+Vue 搭建的简捷开发框架 (4)--NetCore 基础 -2
- .netCore+Vue 搭建的简捷开发框架 (5)
- .netCore+Vue 搭建的简捷开发框架--目录
- AndroidAnnotations开发框架在Eclipse中的搭建和使用以及框架实现的原理
- AndroidAnnotations开发框架在Eclipse中的搭建和使用以及框架实现的原理
- 从零开始搭建前后端分离的NetCore2.2(EF Core CodeFirst+Autofac)+Vue的项目框架之八MemoryCache与redis缓存的使用
- 基于webpack和vue.js搭建的H5端框架(其实主要用于Hybrid开发H5端框架,但是依然能够作为纯web端使用)
- 数据库分库分表(sharding)系列(三) 关于使用框架还是自主开发以及sharding实现层面的考量
- android游戏开发框架libgdx的使用(一)--环境搭建
- Spring4.X + Spring MVC + Mybatis3 零配置应用开发框架搭建详解 (3) - 实现最基本的登录处理
- 使用Mina框架开发 QQ Android 客户端(3) 登陆功能的实现
- 【COCOS2DX-LUA 脚本开发之八】使用quick-cocos2d-x或cocos2dx-LuaProxy的Lua框架实现Lua-Http网络交互!
- 使用Apk动态加载框架(dynamic-load-apk)进行插件开发之环境搭建篇
- win7环境下使用sublime text搭建python开发环境并使用SublimeREPL实现交互操作
- android游戏开发框架libgdx的使用(一)--环境搭建
- Unity3D热更新全书-脚本(四) 用C#LightEvil搭建实际开发使用的脚本框架
- 数据库分库分表(sharding)系列(三) 关于使用框架还是自主开发以及sharding实现层面的考量
- 浅析ButterKnife的实现 (一) —— 搭建开发框架
- 使用lavarel框架进行开发时的环境搭建