EF Core之仓储模式
作者:互联网
仓储模式作为领域驱动设计(Domain-Driven Design,DDD)的一部分,在系统设计中的使用非常广泛。它主要用于解除业务逻辑层与数据访问层之间的耦合,使业务逻辑层在存储、访问数据库时无须关心数据的来源及存储方式,仓储模式带来的好处是一套代码可以适用于多个类,提高代码复用。
话不多说,上代码
1.新建一个仓储接口IRepository
public interface IRepository<T> where T:class { /// <summary> /// 添加 /// </summary> /// <param name="entity">数据实体</param> /// <returns>添加后的数据实体</returns> T Add(T entity); /// <summary> /// 添加 /// </summary> /// <param name="entity">数据实体</param> /// <returns>成功/失败</returns> bool AddOk(T entity); /// <summary> /// 更新 /// </summary> /// <param name="entity">数据实体</param> /// <returns>更新后的数据实体</returns> T Update(T entity); /// <summary> /// 更新 /// </summary> /// <param name="entity">数据实体</param> /// <returns>成功/失败</returns> bool UpdateOk(T entity); /// <summary> /// 删除 /// </summary> /// <param name="id"></param> /// <returns></returns> bool Delete(int id); /// <summary> /// id查询 /// </summary> /// <param name="id"></param> /// <returns></returns> T SelectById(int id); /// <summary> /// 条件查询返回单个实体 /// </summary> /// <param name="whereLambda">查询条件</param> /// <returns></returns> T SelectWhere(Expression<Func<T,bool>> whereLambda); /// <summary> /// 查询全部 /// </summary> /// <returns>集合</returns> List<T> SelectAll(); /// <summary> /// 条件查询返回实体集合 /// </summary> /// <param name="anyLambda">查询条件</param> /// <returns>集合</returns> List<T> SelectList(Expression<Func<T,bool>> whereLambda); /// /// <summary> /// 条件查询且排序 /// </summary> /// <typeparam name="TOrder">排序字段的类型</typeparam> /// <param name="whereLambda">查询条件</param> /// <param name="isAsc">是否升序</param> /// <param name="orderbyLambda">排序条件</param> /// <returns></returns> List<T> SelectList<TOrder>(Expression<Func<T,bool>> whereLambda,bool isAsc,Expression<Func<T, TOrder>> orderbyLambda); /// <summary> /// 分页条件查询且排序 /// </summary> /// <typeparam name="TOrder">排序字段的类型</typeparam> /// <param name="page">分页参数</param> /// <param name="whereLambda">查询条件</param> /// <param name="orderbyLambda">排序条件</param> /// <param name="isAsc">是否升序</param> /// <returns>分页后的结果</returns> PageData<T> SelectPageList<TOrder>(PagePara page, Expression<Func<T, bool>> whereLambda=null, Expression<Func<T, TOrder>> orderbyLambda=null, bool isAsc=false); }
2.建一个实现类Repository
public class Repository<T> : IRepository<T> where T:class { public reflectionContext db = new reflectionContext(); #region 添加 public T Add(T entity) { db.Set<T>().Add(entity); db.SaveChanges(); return entity; } public bool AddOk(T entity) { db.Set<T>().Add(entity); return db.SaveChanges() > 0; } #endregion #region 删除 public bool Delete(int id) { var entity = db.Set<T>().Find(id); db.Set<T>().Remove(entity); return db.SaveChanges() > 0; } #endregion #region 查询 public T SelectById(int id) { return db.Set<T>().Find(id); } public T SelectWhere(Expression<Func<T, bool>> whereLambda) { //.AsNoTracking()非追踪查询 //针对查询,在一些情况下,我们只需要返回一个只读的数据就可以,并不会对数据记录进行任何的修改。这种时候不希望Entity Framework进行不必要的状态变动跟踪, //可以使用Entity Framework的AsNoTracking方法来查询返回不带变动跟踪的查询结果。 //由于是无变动跟踪,所以对返回的数据的没有进行任何修改,在SaveChanges()时,都不会提交到数据库中。 return db.Set<T>().AsNoTracking().FirstOrDefault(whereLambda); } public List<T> SelectList(Expression<Func<T, bool>> whereLambda) { return db.Set<T>().AsNoTracking().Where(whereLambda).ToList(); } public List<T> SelectAll() { return db.Set<T>().AsNoTracking().ToList(); } public List<T> SelectList<TOrder>(Expression<Func<T, bool>> whereLambda, bool isAsc, Expression<Func<T, TOrder>> orderbyLambda) { var list = db.Set<T>().AsNoTracking().Where(whereLambda); if (isAsc) list = list.OrderBy<T, TOrder>(orderbyLambda); else list = list.OrderByDescending<T, TOrder>(orderbyLambda); return list.ToList(); } public PageData<T> SelectPageList<TOrder>(PagePara page, Expression<Func<T, bool>> whereLambda=null, Expression<Func<T, TOrder>> orderbyLambda=null, bool isAsc=false) { var list = db.Set<T>().AsNoTracking(); if (whereLambda!=null) { list = list.Where(whereLambda); } if (orderbyLambda!=null) { if(isAsc) list = list.OrderBy<T, TOrder>(orderbyLambda); else list = list.OrderByDescending<T, TOrder>(orderbyLambda); } PageData<T> pageData = new PageData<T>(); pageData.PageIndex = page.PageIndex; pageData.PageSize = page.PageSize; pageData.Count = list.Count(); pageData.ListData = list.Skip((page.PageIndex - 1) * page.PageSize).Take(page.PageSize).ToList(); return pageData; } #endregion #region 修改 public T Update(T entity) { db.Set<T>().Attach(entity).State = EntityState.Modified; db.SaveChanges(); return entity; } public bool UpdateOk(T entity) { db.Set<T>().Attach(entity).State = EntityState.Modified; return db.SaveChanges() > 0; } #endregion }
其中的分页参数类PagePara和结果类PageData分别如下
/// <summary> /// 分页参数类 /// </summary> public class PagePara { public int PageIndex { get; set; } public int PageSize { get; set; } } public class PageData<T>:PagePara { public int Count { get; set; } public int PageCount { get => Convert.ToInt32(Math.Ceiling(Count /(double) PageSize)); } public List<T> ListData { get; set; } }
然后附上使用方式吧,只需要将泛型替换掉就可以实现仓储的复用了。
static void Main(string[] args) { IRepository<Student> repository = new Repository<Student>(); //新增 Console.WriteLine("---------------------新增----------------------"); Student stu = new Student() {Name = "test1",Age = 33,Likeinfo = "hap"}; stu= repository.Add(stu); Console.WriteLine(stu.Id); //修改 Console.WriteLine("---------------------修改----------------------"); stu.Name = "TEST2"; stu = repository.Update(stu); Console.WriteLine(stu.Name); //删除 //repository.Delete(stu.Id); //id查询 Console.WriteLine("---------------------id查询----------------------"); Student student = repository.SelectById(1); Console.WriteLine(student.Name); //条件查询 Console.WriteLine("---------------------条件查询----------------------"); student = repository.SelectWhere(n => n.Name == "小黑"); Console.WriteLine(student.Name); //查询全部 Console.WriteLine("---------------------查询全部----------------------"); var stuList = repository.SelectAll(); Console.WriteLine(JsonConvert.SerializeObject(stuList)); //条件查询排序 Console.WriteLine("---------------------条件查询,排序----------------------"); stuList = repository.SelectList(x => x.Name.Contains("小"),false,x=>x.Age); Console.WriteLine(JsonConvert.SerializeObject(stuList)); //条件分页查询 Console.WriteLine("---------------------条件分页查询----------------------"); PagePara pagePara = new PagePara { PageIndex = 1, PageSize = 2 }; var pageData = repository.SelectPageList<Student>(pagePara); Console.WriteLine(JsonConvert.SerializeObject(pageData)); }
后来改良版:
public interface IRepository<TEntity, TPrimaryKey> where TEntity : class { #region 查询 /// <summary> /// 获取用于从整个表中检索实体的IQueryable /// </summary> /// <returns>可用于从数据库中选择实体</returns> IQueryable<TEntity> GetAll(); /// <summary> /// 用于获取所有实体 /// </summary> /// <returns>所有实体列表</returns> List<TEntity> GetAllList(); /// <summary> /// 用于获取所有实体的异步实现 /// </summary> /// <returns>所有实体列表</returns> Task<List<TEntity>> GelAllListAsync(); /// <summary> /// 用于获取传入本方法的所有实体 /// </summary> /// <param name="predicate">筛选实体的条件</param> /// <returns>所有实体列表</returns> List<TEntity> GetAllList(Expression<Func<TEntity, bool>> predicate); /// <summary> /// 用于获取传入本方法的所有实体 /// </summary> /// <param name="predicate">筛选实体的条件</param> /// <returns>所有实体列表</returns> Task<List<TEntity>> GetAllListAsync(Expression<Func<TEntity, bool>> predicate); /// <summary> /// 通过传入的筛选条件来获取实体信息 /// 如果查询不到返回值,则会引发异常 /// </summary> /// <param name="predicate"></param> /// <returns></returns> TEntity Single(Expression<Func<TEntity, bool>> predicate); /// <summary> /// 通过传入的筛选条件来获取实体信息 /// 如果查询不到返回值,则会引发异常 /// </summary> /// <param name="predicate"></param> /// <returns></returns> Task<TEntity> SingleAsync(Expression<Func<TEntity, bool>> predicate); /// <summary> /// 通过传入的筛选条件查询实体信息,如果没有找到,则返回null /// </summary> /// <param name="predicate"></param> /// <returns></returns> TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate); /// <summary> /// 通过传入的筛选条件查询实体信息,如果没有找到,则返回null /// </summary> /// <param name="predicate"></param> /// <returns></returns> Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate); #endregion #region 添加 /// <summary> /// 添加一个新实体 /// </summary> /// <param name="entity">被添加的实体</param> /// <returns></returns> TEntity Insert(TEntity entity); /// <summary> /// 添加一个新实体 /// </summary> /// <param name="entity">被添加的实体</param> /// <returns></returns> Task<TEntity> InsertAsync(TEntity entity); #endregion #region 修改 /// <summary> /// 更新现有实体 /// </summary> /// <param name="entity"></param> /// <returns></returns> TEntity Update(TEntity entity); /// <summary> /// 更新现有实体 /// </summary> /// <param name="entity"></param> /// <returns></returns> Task<TEntity> UpdateAsync(TEntity entity); #endregion #region 删除 /// <summary> /// 删除一个实体 /// </summary> /// <param name="entity">无返回值</param> void Delete(TEntity entity); /// <summary> /// 删除一个实体 /// </summary> /// <param name="entity">无返回值</param> /// <returns></returns> Task DeleteAsync(TEntity entity); /// <summary> /// 传入的条件可删除多个实体 /// 注意:所有符合给定条件的实体都将被检索和删除 /// 如果条件比较多,则待删除的实体也比较多,则可能会导致主要的性能问题 /// </summary> /// <param name="predicate"></param> void Delete(Expression<Func<TEntity, bool>> predicate); /// <summary> /// 传入的条件可删除多个实体 /// 注意:所有符合给定条件的实体都将被检索和删除 /// 如果条件比较多,则待删除的实体也比较多,则可能会导致主要的性能问题 /// </summary> /// <param name="predicate"></param> Task DeleteAsync(Expression<Func<TEntity, bool>> predicate); #endregion #region 总和计算 /// <summary> /// 获取此仓储中所有实体的总和 /// </summary> /// <returns>实体的总数</returns> int Count(); /// <summary> /// 获取此仓储中所有实体的总和 /// </summary> /// <returns>实体的总数</returns> Task<int> CountAsync(); /// <summary> /// 支持条件筛选计算仓储中的实体总和 /// </summary> /// <param name="predicate"></param> /// <returns>实体的总数</returns> int Count(Expression<Func<TEntity, bool>> predicate); /// <summary> /// 支持条件筛选计算仓储中的实体总和 /// </summary> /// <param name="predicate"></param> /// <returns>实体的总数</returns> Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate); /// <summary> /// 获取此存储库中所有的实体的总和,如果返回值大于了Int.MaxValue值,则推荐该方法 /// </summary> /// <returns>实体的总和</returns> long LongCount(); /// <summary> /// 获取此存储库中所有的实体的总和,如果返回值大于了Int.MaxValue值,则推荐该方法 /// </summary> /// <returns>实体的总和</returns> Task<long> LongCountAsync(); /// <summary> /// 获取此存储库中所有的实体的总和,如果返回值大于了Int.MaxValue值,则推荐该方法 /// </summary> /// <returns>实体的总和</returns> long LongCount(Expression<Func<TEntity, bool>> predicate); /// <summary> /// 获取此存储库中所有的实体的总和,如果返回值大于了Int.MaxValue值,则推荐该方法 /// </summary> /// <returns>实体的总和</returns> Task<long> LongCountAsync(Expression<Func<TEntity, bool>> predicate); #endregion }
public class Repository<TEntity, TPrimaryKey> : IRepository<TEntity, TPrimaryKey> where TEntity : class { /// <summary> /// 数据库上下文 /// </summary> private readonly XXXDbContext _db; // 非依赖注入使用 XXXDbContext _db = new XXXDbContext(); /// <summary> /// 通过泛型,从数据库上下文中获取领域模型 /// </summary> public virtual DbSet<TEntity> Table => _db.Set<TEntity>(); /// <summary> /// 依赖注入 /// </summary> public Repository(XXXDbContext db) { _db = db; } protected void Save() { _db.SaveChanges(); } /// <summary> /// 检查实体是否处于跟踪状态,如果是,则返回;如果不是,则添加跟踪状态 /// </summary> /// <param name="entity"></param> protected virtual void AttachIfNot(TEntity entity) { var entry = _db.ChangeTracker.Entries().FirstOrDefault(ent => ent.Entity == entity); if (entry != null) { return; } Table.Attach(entity); } protected async Task SaveAsync() { await _db.SaveChangesAsync(); } public IQueryable<TEntity> GetAll() { return Table.AsQueryable(); } public List<TEntity> GetAllList() { return GetAll().ToList(); } public async Task<List<TEntity>> GelAllListAsync() { return await GetAll().ToListAsync(); } public List<TEntity> GetAllList(Expression<Func<TEntity, bool>> predicate) { return GetAll().Where(predicate).ToList(); } public async Task<List<TEntity>> GetAllListAsync(Expression<Func<TEntity, bool>> predicate) { return await GetAll().Where(predicate).ToListAsync(); } public TEntity Single(Expression<Func<TEntity, bool>> predicate) { return GetAll().Single(predicate); } public async Task<TEntity> SingleAsync(Expression<Func<TEntity, bool>> predicate) { return await GetAll().SingleAsync(predicate); } public TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate) { return GetAll().FirstOrDefault(predicate); } public async Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate) { return await GetAll().FirstOrDefaultAsync(predicate); } public TEntity Insert(TEntity entity) { var newEntity = Table.Add(entity).Entity; Save(); return newEntity; } public async Task<TEntity> InsertAsync(TEntity entity) { var newEntity = (await Table.AddAsync(entity)).Entity; await SaveAsync(); return newEntity; } public TEntity Update(TEntity entity) { AttachIfNot(entity); _db.Entry(entity).State = EntityState.Modified; Save(); return entity; } public async Task<TEntity> UpdateAsync(TEntity entity) { AttachIfNot(entity); _db.Entry(entity).State = EntityState.Modified; await SaveAsync(); return entity; } public void Delete(TEntity entity) { AttachIfNot(entity); Table.Remove(entity); Save(); } public async Task DeleteAsync(TEntity entity) { AttachIfNot(entity); Table.Remove(entity); await SaveAsync(); } public void Delete(Expression<Func<TEntity, bool>> predicate) { foreach (var entity in GetAll().Where(predicate).ToList()) { Delete(entity); } } public async Task DeleteAsync(Expression<Func<TEntity, bool>> predicate) { foreach (var entity in GetAll().Where(predicate).ToList()) { await DeleteAsync(entity); } } public int Count() { return GetAll().Count(); } public async Task<int> CountAsync() { return await GetAll().CountAsync(); } public int Count(Expression<Func<TEntity, bool>> predicate) { return GetAll().Where(predicate).Count(); } public async Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate) { return await GetAll().Where(predicate).CountAsync(); } public long LongCount() { return GetAll().LongCount(); } public async Task<long> LongCountAsync() { return await GetAll().LongCountAsync(); } public long LongCount(Expression<Func<TEntity, bool>> predicate) { return GetAll().Where(predicate).LongCount(); } public async Task<long> LongCountAsync(Expression<Func<TEntity, bool>> predicate) { return await GetAll().Where(predicate).LongCountAsync(); } }
需要源码的可以加.net core学习交流群:831181779,在群里@群主即可
转 https://blog.csdn.net/hyx1229/article/details/120357777
标签:Core,predicate,实体,return,EF,entity,仓储,Expression,public 来源: https://www.cnblogs.com/wl-blog/p/16339098.html