為什麼要使用泛型倉儲?好處是? 前兩章在autofac註入的時候,用的User類作為例子,寫了增刪改查四個介面,也就是倉儲的GRUD。 當我們再添加一個實體(比如Student)時,StudentRepository跟UserRepository代碼幾乎一樣的代碼,重覆量很大,為了減少冗餘、提高工作 ...
為什麼要使用泛型倉儲?好處是?
前兩章在autofac註入的時候,用的User類作為例子,寫了增刪改查四個介面,也就是倉儲的GRUD。
當我們再添加一個實體(比如Student)時,StudentRepository跟UserRepository代碼幾乎一樣的代碼,重覆量很大,為了減少冗餘、提高工作效率,使用泛型倉儲最好不過了
好處:
減少代碼冗餘
提高了開發人員的工作效率
提高對資料庫訪問的維護
一、泛型倉儲介面和泛型倉儲實現類
泛型倉儲介面
在類庫項目上右鍵->添加->新建文件夾,命名為Repository,存放泛型倉儲類。在Repository文件夾下麵新建 泛型倉儲介面類:IRepository,如下:
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using NetCoreWebApi.Repository.Dto; namespace NetCoreWebApi.Repository.Repository { public interface IRepository<T> where T : class { /// <summary> /// 添加實體(單個) /// </summary> /// <param name="entity">實體對象</param> int Add(T entity); /// <summary> /// 批量插入實體(多個) /// </summary> /// <param name="list">實體列表</param> int AddRange(List<T> list); /// <summary> /// 刪除實體(單個) /// </summary> /// <param name="entity"></param> int Remove(T entity); /// <summary> /// 批量刪除實體(多個) /// </summary> /// <param name="list">實體列表</param> int RemoveRange(List<T> list); /// <summary> /// 獲取所有 /// </summary> /// <returns></returns> IQueryable<T> GetAll(); /// <summary> /// 分頁條件查詢 /// </summary> /// <typeparam name="TKey">排序類型</typeparam> /// <param name="pageIndex">當前頁</param> /// <param name="pageSize">每頁大小</param> /// <param name="predicate">條件表達式</param> /// <param name="isAsc">是否升序排列</param> /// <param name="keySelector">排序表達式</param> /// <returns></returns> Page<T> SearchFor<TKey>(int pageIndex, int pageSize, Expression<Func<T, bool>> predicate, bool isAsc, Expression<Func<T, TKey>> keySelector); /// <summary> /// 獲取實體(主鍵) /// </summary> /// <param name="id">主鍵id</param> /// <returns></returns> T GetModelById(object id); /// <summary> /// 獲取實體(條件) /// </summary> /// <param name="predicate">條件表達式</param> /// <returns></returns> T GetModel(Expression<Func<T, bool>> predicate); /// <summary> /// 查詢記錄數 /// </summary> /// <param name="predicate">條件表達式</param> /// <returns>記錄數</returns> int Count(Expression<Func<T, bool>> predicate); /// <summary> /// 是否存在 /// </summary> /// <param name="anyLambda">查詢表達式</param> /// <returns>布爾值</returns> bool Exist(Expression<Func<T, bool>> anyLambda); } }
泛型倉儲實現類
在Repository文件夾下麵新建 泛型倉儲實現類:Repository,並繼承IRepository,如下:
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore; using NetCoreWebApi.Model; using NetCoreWebApi.Repository.Dto; namespace NetCoreWebApi.Repository.Repository { public class Repository<T> : IRepository<T> where T : class { private readonly MyDbContext _dbContext; private DbSet<T> _entity; /// <summary> /// 構造函數 /// </summary> /// <param name="dbContext"></param> public Repository(MyDbContext dbContext) { _dbContext = dbContext; } private DbSet<T> Entity => _entity ?? (_entity = _dbContext.Set<T>()); /// <summary> /// 添加實體(單個) /// </summary> /// <param name="entity">實體對象</param> public int Add(T entity) { Entity.Add(entity); return _dbContext.SaveChanges(); } /// <summary> /// 批量插入實體(多個) /// </summary> /// <param name="list">實體列表</param> public int AddRange(List<T> list) { Entity.AddRange(list); return _dbContext.SaveChanges(); } /// <summary> /// 刪除實體(單個) /// </summary> /// <param name="entity"></param> public int Remove(T entity) { Entity.Remove(entity); return _dbContext.SaveChanges(); } /// <summary> /// 批量刪除實體(多個) /// </summary> /// <param name="list">實體列表</param> public int RemoveRange(List<T> list) { Entity.RemoveRange(list); return _dbContext.SaveChanges(); } /// <summary> /// 獲取所有 /// </summary> /// <returns></returns> public IQueryable<T> GetAll() { return Entity.AsQueryable().AsNoTracking(); } /// <summary> /// 條件查詢 /// </summary> /// <typeparam name="TKey">排序類型</typeparam> /// <param name="pageIndex">當前頁</param> /// <param name="pageSize">每頁大小</param> /// <param name="isAsc">是否升序排列</param> /// <param name="predicate">條件表達式</param> /// <param name="keySelector">排序表達式</param> /// <returns></returns> public Page<T> SearchFor<TKey>(int pageIndex, int pageSize, Expression<Func<T, bool>> predicate, bool isAsc, Expression<Func<T, TKey>> keySelector) { if (pageIndex <= 0 || pageSize <= 0) throw new Exception("pageIndex或pageSize不能小於等於0"); var page = new Page<T> { PageIndex = pageIndex, PageSize = pageSize }; var skip = (pageIndex - 1) * pageSize; var able = Entity.AsQueryable().AsNoTracking(); if (predicate == null) { var count = Entity.Count(); var query = isAsc ? able.OrderBy(keySelector).Skip(skip).Take(pageSize) : able.OrderByDescending(keySelector).Skip(skip).Take(pageSize); page.TotalRows = count; page.LsList = query.ToList(); page.TotalPages = page.TotalRows / pageSize; if (page.TotalRows % pageSize != 0) page.TotalPages++; } else { var queryable = able.Where(predicate); var count = queryable.Count(); var query = isAsc ? queryable.OrderBy(keySelector).Skip(skip).Take(pageSize) : queryable.OrderByDescending(keySelector).Skip(skip).Take(pageSize); page.TotalRows = count; page.LsList = query.ToList(); page.TotalPages = page.TotalRows / pageSize; if (page.TotalRows % pageSize != 0) page.TotalPages++; } return page; } /// <summary> /// 獲取實體 /// </summary> /// <param name="id">主鍵id</param> /// <returns></returns> public T GetModelById(object id) { return Entity.Find(id); } /// <summary> /// 獲取實體(條件) /// </summary> /// <param name="predicate">條件表達式</param> /// <returns></returns> public T GetModel(Expression<Func<T, bool>> predicate) { return Entity.FirstOrDefault(predicate); } /// <summary> /// 查詢記錄數 /// </summary> /// <param name="predicate"></param> /// <returns></returns> public int Count(Expression<Func<T, bool>> predicate) { return predicate != null ? Entity.Where(predicate).Count() : Entity.Count(); } /// <summary> /// 是否存在 /// </summary> /// <param name="anyLambda"></param> /// <returns></returns> public bool Exist(Expression<Func<T, bool>> anyLambda) { return Entity.Any(anyLambda); } } }
分頁Page類
using System.Collections.Generic; namespace NetCoreWebApi.Repository.Dto { public class Page<T> { /// <summary> /// 當前頁 /// </summary> public int PageIndex { get; set; } /// <summary> /// 總頁數 /// </summary> public int TotalPages { get; set; } /// <summary> /// 集合總數 /// </summary> public int TotalRows { get; set; } /// <summary> /// 每頁項數 /// </summary> public int PageSize { get; set; } /// <summary> /// 集合 /// </summary> public IList<T> LsList { get; set; } } }
二、倉儲的泛型的依賴註入。
修改Startup.cs啟動類中ConfigureServices方法
public static IContainer ApplicationContainer { get; set; } /// <summary> /// //負責註入服務 /// </summary> /// <param name="services"></param> /// <returns></returns> public IServiceProvider ConfigureServices(IServiceCollection services) { //獲取資料庫連接字元串 var connectionStr = Configuration.GetConnectionString("SqlServer"); services.AddDbContext<MyDbContext> (options => options.UseSqlServer(connectionStr, e => e.MigrationsAssembly("NetCoreWebApi.Model"))); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); //初始化容器 var builder = new ContainerBuilder(); //管道寄居 builder.Populate(services); //註冊業務 builder.RegisterAssemblyTypes(Assembly.Load("NetCoreWebApi.Repository"), Assembly.Load("NetCoreWebApi.Repository")) .Where(t => t.Name.EndsWith("Repository")) .AsImplementedInterfaces(); //註冊倉儲,所有IRepository介面到Repository的映射 builder.RegisterGeneric(typeof(Repository<>)) //InstancePerDependency:預設模式,每次調用,都會重新實例化對象;每次請求都創建一個新的對象; .As(typeof(IRepository<>)).InstancePerDependency(); //構造 ApplicationContainer = builder.Build(); //將AutoFac反饋到管道中 return new AutofacServiceProvider(ApplicationContainer); }
三、測試
修改業務層---UserRepository
給泛型類指定ThUser,紅色字體是主要更改部分。
using System.Collections.Generic; using System.Linq; using NetCoreWebApi.Model.Models; using NetCoreWebApi.Repository.Interface; using NetCoreWebApi.Repository.Repository; namespace NetCoreWebApi.Repository.Implement { /// <summary> /// 業務處理 /// </summary> public class UserRepository:IUserRepository { private readonly IRepository<TbUser> _userRepository; /// <summary> /// 構造函數 /// </summary> /// <param name="userRepository"></param> public UserRepository(IRepository<TbUser> userRepository) { _userRepository = userRepository; } /// <summary> /// 添加用戶 /// </summary> /// <param name="entity"></param> /// <returns></returns> public int Add(TbUser entity) { return _userRepository.Add(entity); } /// <summary> /// 刪除用戶 /// </summary> /// <param name="entity"></param> /// <returns></returns> public int Remove(TbUser entity) { return _userRepository.Remove(entity); } /// <summary> /// 查詢用戶 /// </summary> /// <returns></returns> public IList<TbUser> GetAll() { return _userRepository.GetAll().ToList(); } } }
運行項目執行介面,可以看到跟之前一樣
如果有其他實體只需要改變傳入的T就可以了,不需要再重新創建TEntityRepository