EF Core之仓储模式

2022/6/2 23:21:09

本文主要是介绍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



这篇关于EF Core之仓储模式的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程