為什么要使用泛型倉儲?好處是?
前兩章在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(); } /// <summary> /// 條件查詢 /// </summary> /// <param name="name">姓名</param> /// <param name="isAsc">是否正序</param> /// <param name="pageIndex">頁碼</param> /// <param name="pageSize">每頁大小</param> /// <returns></returns> public object SearchFor(string name, bool isAsc, int pageIndex, int pageSize) { //條件運算式 Expression<Func<TbUser, bool>> predicate = e => string.IsNullOrWhiteSpace(name) || e.UserName.Equals(name); var data = https://www.cnblogs.com/tenghao510/p/_userRepository.SearchFor(pageIndex, pageSize, predicate, isAsc, e=>e.CreateTime); return data; } } }
多條件查詢
稍微修改下條件查詢介面
/// <summary> /// 條件查詢 /// </summary> /// <param name="name">姓名</param> /// <param name="name1">姓名1</param> /// <param name="isAsc">是否正序</param> /// <param name="pageIndex">頁碼</param> /// <param name="pageSize">每頁大小</param> /// <returns></returns> public object SearchFor(string name, string name1, bool isAsc, int pageIndex, int pageSize) { //條件運算式 Expression<Func<TbUser, bool>> predicate = e => (string.IsNullOrWhiteSpace(name) || e.UserName.Equals(name))&& (string.IsNullOrWhiteSpace(name1)||e.UserName.Equals(name1)); var data = https://www.cnblogs.com/tenghao510/p/_userRepository.SearchFor(pageIndex, pageSize, predicate, isAsc, e=>e.CreateTime); return data; }
運行專案執行介面,可以看到跟之前一樣

如果有其他物體只需要改變傳入的T就可以了,不需要再重新創建TEntityRepository
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/89728.html
標籤:.NET Core
