.NET5中的EF Core数据层仓储模式

Posted 棉晗榜

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了.NET5中的EF Core数据层仓储模式相关的知识,希望对你有一定的参考价值。

使用EF框架:
Microsoft.EntityFrameworkCore

Microsoft.EntityFrameworkCore.SqlServer

程序集框架.NET5

DbContext数据上下文配置

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore.Diagnostics;
using WebMvcNetCore.TuShi.FenGong.Model;

namespace WebMvcNetCore.TuShi.FenGong.DAL_Impl
{
    /// <summary>
    /// EF数据上下文
    /// </summary>
    /// <remarks>
    /// 创建时间:2021-7-29 10:02:152
    /// 作者:王浩力
    /// </remarks>
    public class MyDbContext : DbContext
    {
        //public MyDbContext()
        //{
        //    //设置执行超时限制
        //    //this.Database.SetCommandTimeout(60);
        //}

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            //连接字符串配置
            //#connctionDb   server=.;Database=gdd_tu_shi_fen_gong;uid=sa;pwd=123456
            string connectionString = MyConfigReader.GetConfigValue("connctionDb");

#if WPF_Debug || WPF_Release

            //如果是WPF端,连接字符串是加密的,这里需要解密
            connectionString = FenGong.Model.Tool.AesHelpter.AESDecryptByHex(connectionString);

#endif

            optionsBuilder.UseSqlServer(connectionString);


            //设置不跟踪所有查询  
            optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);

            //启用敏感数据日志记录
            optionsBuilder.EnableSensitiveDataLogging();

#if DEBUG
            //记录日志          
            optionsBuilder.LogTo(msg =>
            {
                //调试-窗口消息
                System.Diagnostics.Debug.WriteLine(msg);
                //输出-窗口消息
                Console.WriteLine(msg);
            });
#endif

        }

        public virtual DbSet<Animation> Animation { get; set; }
        public virtual DbSet<Animation_step> Animation_step { get; set; }
        public virtual DbSet<Ground_lead> Ground_lead { get; set; }
        public virtual DbSet<Map_mark> Map_mark { get; set; }
   
        

    }
}

数据层接口

//功用:数据保存
//创建时间:2020-12-24 14:10:11
//作者:王浩力

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WebMvcNetCore.TuShi.FenGong.Model;

namespace WebMvcNetCore.TuShi.FenGong.IDAL
{
    /// <summary>
    /// 数据操作基接口
    /// </summary>
    public interface IDaoBase<T> where T : class
    {
        /// <summary>
        /// 新增一条,同步执行
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        int Add(T entity);

        /// <summary>
        /// 新增一条,异步执行
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        Task<int> AddAsync(T entity);

        /// <summary>
        /// 新增多条记录,同步执行
        /// </summary>
        /// <param name="entitys"></param>
        /// <returns></returns>
        int Add(IEnumerable<T> entitys);

        /// <summary>
        /// 新增多条,异步执行
        /// </summary>
        /// <param name="entitys"></param>
        /// <returns></returns>
        Task<int> AddListAsync(IEnumerable<T> entitys);

        /// <summary>
        /// 修改一条,同步执行
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        int Update(T entity);

        /// <summary>
        /// 修改一条,异步执行
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        Task<int> UpdateAsync(T entity);

        /// <summary>
        /// 修改指定的字段
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="column"></param>
        /// <returns></returns>
        Task<int> UpdateAsync(T entity, string[] column);

        /// <summary>
        /// 异步修改集合,修改指定的列
        /// </summary>
        /// <param name="list">集合</param>
        /// <param name="column">指定的列,参考 id,name。要修改的列名传入数组</param>
        /// <returns></returns>
        Task<int> UpdateListAsync(List<T> list, string[] column);

        /// <summary>
        ///  [事务]批量修改或新增或删除(若干个)
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        Task<int> SaveMultipleAsync(List<SaveModel> list);

        int Delete(T entity);

        /// <summary>
        /// 根据主键删除一条
        /// </summary>
        /// <param name="id">主键值</param>
        /// <returns></returns>
        Task<int> DeleteByPrimaryKeyAsync(object id);
        Task<int> DeleteAsync(T entity);
        int Delete(Expression<Func<T, bool>> where);
        Task<int> DeleteAsync(Expression<Func<T, bool>> where);

        /// <summary>
        /// 根据主键查询一条
        /// </summary>
        /// <param name="id">主键</param>
        /// <returns></returns>
        T Get(object id);

        /// <summary>
        /// 根据主键异步查询
        /// </summary>
        /// <param name="id">主键</param>
        /// <returns></returns>
        Task<T> GetAsync(object id);

        T Get(Expression<Func<T, bool>> where);

        /// <summary>
        /// 异步查询单条记录
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<T> GetSingleOrDefaultAsync(Expression<Func<T, bool>> where);

        /// <summary>
        /// 条件查询所有记录,返回IQueryable<T>
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        IQueryable<T> GetList(Expression<Func<T, bool>> where);

        /// <summary>
        /// 使用新的数据上下文
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        IQueryable<T> GetListByNewContext(Expression<Func<T, bool>> where);

        /// <summary>
        /// 同步,查询表所有记录
        /// </summary>
        /// <returns></returns>
        List<T> GetListAll();

        /// <summary>
        /// 条件查询所有记录
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns></returns>
        List<T> GetListAll(Expression<Func<T, bool>> where);

        /// <summary>
        /// 异步查询集合
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns></returns>
        Task<List<T>> GetListAsync(Expression<Func<T, bool>> where);

        /// <summary>
        /// 异步查询所有记录
        /// </summary>
        /// <returns></returns>
        Task<List<T>> GetAllListAsync();

        /// <summary>
        /// Query查询
        /// </summary>
        /// <returns></returns>
        IQueryable<T> GetQuery();
        IQueryable<T> GetQuery(Expression<Func<T, bool>> where);
 
        /// <summary>
        /// 检查是否存在
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        bool Any(Expression<Func<T, bool>> where);

        /// <summary>
        /// 检查是否存在
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<bool> AnyAsync(Expression<Func<T, bool>> where);

        /// <summary>
        /// 根据条件查询个数
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns></returns>
        int Count(Expression<Func<T, bool>> where);
        Task<int> CountAsync(Expression<Func<T, bool>> where);

        PageModel<G> GetPage<G>(IQueryable<G> query, int pageIndex, int pageSize);
        PageModel<T> GetPage<SortKey>(int pageIndex, int pageSize, Expression<Func<T, bool>> where, Expression<Func<T, SortKey>> orderwhere);

        /// <summary>
        /// 异步,分页查询升序
        /// </summary>
        /// <typeparam name="SortKey">排序字段类型,可省略</typeparam>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="where"></param>
        /// <param name="orderByAsc"></param>
        /// <returns></returns>
        /// 2019-10-15 17:17:09 王浩力 添加
        Task<PageModel<T>> GetPageAsync<SortKey>(int pageIndex, int pageSize, Expression<Func<T, bool>> where, Expression<Func<T, SortKey>> orderByAsc);

        /// <summary>
        /// 异步分页,倒序查询
        /// </summary>
        /// <typeparam name="SortKey">排序字段类型,可省略</typeparam>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">每页记录数</param>
        /// <param name="where">查询条件</param>
        /// <param name="orderByDesc">倒序列</param>
        /// <returns></returns>
        Task<PageModel<T>> GetPageOrderByDescAsync<SortKey>(int pageIndex, int pageSize, Expression<Func<T, bool>> where, Expression<Func<T, SortKey>> orderByDesc);

        /// <summary>
        /// 表联合查询时,可用此方法
        /// </summary>
        /// <typeparam name="G">视图实体类型,装了多个表字段的实体</typeparam>
        /// <param name="query"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        Task<PageModel<G>> GetPageAsync<G>(IQueryable<G> query, int pageIndex, int pageSize);

        /// <summary>
        /// 扩展 IQueryable<T>.ToListAsync();,此方法非常实用,可以在bll业务层使用
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        Task<List<G>> ToListAsync<G>(IQueryable<G> query);
    }
}


数据层接口实现

//功用:数据保存
//创建时间:2020-12-24 14:10:11
//作者:王浩力
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WebMvcNetCore.TuShi.FenGong.IDAL;
using WebMvcNetCore.TuShi.FenGong.Model;
using WebMvcNetCore.TuShi.FenGong.Model.Tool;

namespace WebMvcNetCore.TuShi.FenGong.DAL_Impl
{
    /// <summary>
    /// 数据处理 实现
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class DaoBase<T> : IDaoBase<T> where T : class 
    {
        /*
         * https://docs.microsoft.com/zh-cn/ef/core/dbcontext-configuration/#avoiding-dbcontext-threading-issues
         避免 DbContext 线程处理问题
Entity Framework Core 不支持在同一 DbContext 实例上运行多个并行操作。 这包括异步查询的并行执行以及从多个线程进行的任何显式并发使用。 因此,始终立即 await 异步调用,或对并行执行的操作使用单独的 DbContext 实例。
当 EF Core 检测到尝试同时使用 DbContext 实例的情况时,你将看到 InvalidOperationException,其中包含类似于以下内容的消息:
在上一个操作完成之前,第二个操作已在此上下文中启动。 这通常是由使用同一个 DbContext 实例的不同线程引起的,但不保证实例成员是线程安全的。
检测不到并发访问时,可能会导致未定义的行为、应用程序崩溃和数据损坏         
         */
        //每次查询使用新的DbContext,防止并发异常

        /// <summary>
        /// ef数据上下文
        /// </summary>
        protected readonly MyDbContext dbContext;

        /// <summary>
        /// 当前T类型对应的表
        /// </summary>
        protected readonly DbSet<T> dbSet;

        public DaoBase()
        {
            dbContext = new MyDbContext();
            dbSet = dbContext.Set<T>();
        }

        /// <summary>
        /// 获取新的DbContext
        /// </summary>
        /// <returns></returns>
        public MyDbContext GetNewDbContext()
        {
            return new MyDbContext();
        }

        /// <summary>
        /// 获取没有上下文缓存的新查询
        /// </summary>
        /// <returns></returns>
        protected IQueryable<T> GetDbsetNoCacheQueryable()
        {
            return dbSet.AsNoTracking();
        }

        public int Add(T entity)
        {
            dbSet.Add(entity);
            return dbContext.SaveChanges();
        }

        public async Task<int> AddAsync(T entity)
        {
            dbSet.Add(entity);
            return await dbContext.SaveChangesAsync();
        }

        public int Add(IEnumerable<T> entitys)
        {
            foreach (var entity in entitys)
            {
                dbSet.Add(entity);
            }
            return dbContext.SaveChanges();
        }

        public async Task<int> AddListAsync(IEnumerable<T> entitys)
        {
            //  await dbSet.AddRangeAsync(entitys);
            dbSet.AddRange(entitys);
            return await dbContext.SaveChangesAsync();
        }

        public int Update(T entity)
        {
            MyDbContext dbContextUpdate = new MyDbContext();
            dbContextUpdate.Entry(entity).State = EntityState.Modified;
            return dbContextUpdate.SaveChanges();
        }

        public async Task<int> UpdateAsync(T entity)
        {
            try
            {
                DbContext dbContextUpdate = new MyDbContext();
                dbContextUpdate.Entry(entity).State = EntityState.Modified;
                return await dbContextUpdate.SaveChangesAsync();
            }
            catch (Exception e)
            {
                return 0;
            }
        }

        public int Update(IEnumerable<T> entitys)
        {
            DbContext dbContextUpdate = new MyDbContext();
            foreach (var entity in entitys)
            {
                dbContextUpdate.Entry(entity)以上是关于.NET5中的EF Core数据层仓储模式的主要内容,如果未能解决你的问题,请参考以下文章

EF Core-1

Abp vNext 自定义 Ef Core 仓储引发异常

ASP.NET 5/ASP.NET Core 1 中的关注点分离和 n 层架构

.NET Core MongoDB数据仓储和工作单元模式封装

NopCommerce用core重写ef

OSS.Core基于Dapper封装(表达式解析+Emit)仓储层的构思及实现