爲何要使用泛型倉儲?好處是?數據庫
前兩章在autofac注入的時候,用的User類做爲例子,寫了增刪改查四個接口,也就是倉儲的GRUD。ide
當咱們再添加一個實體(好比Student)時,StudentRepository跟UserRepository代碼幾乎同樣的代碼,重複量很大,爲了減小冗餘、提升工做效率,使用泛型倉儲最好不過了函數
好處:測試
減小代碼冗餘字體
提升了開發人員的工做效率ui
提升對數據庫訪問的維護spa
在類庫項目上右鍵->添加->新建文件夾,命名爲Repository,存放泛型倉儲接口及實現類。在Repository文件夾下面新建 泛型倉儲接口類:IRepository,以下:code
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); } } }
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方法blog
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); }
給泛型類指定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