利用EFCore 封裝Repository(可擴展不同數據的sql操作)

来源:https://www.cnblogs.com/lxshwyan/archive/2019/04/30/10794412.html
-Advertisement-
Play Games

本篇是對EFCore 進行下封裝並實現基本的增刪改查的同步非同步方法及針對不同資料庫的批量插入、sql語句直接操作資料庫; 一、 先定義基礎倉儲介面IRepository 二、實現IRepository介面 三、BaseRepository是個抽象類,有些比較複雜的sql語句通過EF來處理比較麻煩,還 ...


             本篇是對EFCore 進行下封裝並實現基本的增刪改查的同步非同步方法及針對不同資料庫的批量插入、sql語句直接操作資料庫;

       一、 先定義基礎倉儲介面IRepository

   

  public  interface IRepository<TEntity,TKey> where TEntity : class
    {
        #region 查找數據
        long Count(Expression<Func<TEntity, bool>> predicate = null);
        Task<long> CountAsync(Expression<Func<TEntity, bool>> predicate = null);

        TEntity Get(Expression<Func<TEntity, bool>> predicate, bool isNoTracking);
        Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> predicate, bool isNoTracking);

     
        Task<TEntity> GetAsync(TKey id);

        IQueryable<TEntity> Load(Expression<Func<TEntity, bool>> predicate , bool isNoTracking);
        Task<IQueryable<TEntity>> LoadAsync(Expression<Func<TEntity, bool>> predicate , bool isNoTracking);

        List<TEntity> GetList(Expression<Func<TEntity, bool>> predicate, string ordering, bool isNoTracking );
        Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate, string ordering, bool isNoTracking );
       
        #endregion

        #region 插入數據
        bool Insert(TEntity entity, bool isSaveChange);
        Task<bool> InsertAsync(TEntity entity, bool isSaveChange);
        bool Insert(List<TEntity> entitys, bool isSaveChange = true);
        Task<bool> InsertAsync(List<TEntity> entitys, bool isSaveChange);
        #endregion

        #region 刪除(刪除之前需要查詢)
        bool Delete(TEntity entity, bool isSaveChange);
        bool Delete(List<TEntity> entitys, bool isSaveChange);
        Task<bool> DeleteAsync(TEntity entity, bool isSaveChange);
        Task<bool> DeleteAsync(List<TEntity> entitys, bool isSaveChange = true);
        #endregion

        #region 修改數據
       bool Update(TEntity entity, bool isSaveChange, List<string> updatePropertyList);
       Task<bool> UpdateAsync(TEntity entity, bool isSaveChange, List<string> updatePropertyList);
       bool Update(List<TEntity> entitys, bool isSaveChange);
       Task<bool> UpdateAsync(List<TEntity> entitys, bool isSaveChange );
        #endregion

        #region 執行Sql語句
        void BulkInsert<T>(List<T> entities);
        int ExecuteSql(string sql);
        Task<int> ExecuteSqlAsync(string sql);
        int ExecuteSql(string sql, List<DbParameter> spList);
        Task<int> ExecuteSqlAsync(string sql, List<DbParameter> spList);
        DataTable GetDataTableWithSql(string sql);

        DataTable GetDataTableWithSql(string sql, List<DbParameter> spList);

      

        #endregion

二、實現IRepository介面

   public abstract  class BaseRepository<TEntity,TKey> :IRepository<TEntity,TKey> where TEntity : class
    {
        private readonly DbSet<TEntity> _dbSet;
        public GeneralDbContext _dbContext { get; } = null;

        /// <summary>
        /// 連接字元串
        /// </summary>
        protected string _connectionString { get; set; }

        /// <summary>
        /// 資料庫類型
        /// </summary>
        private DatabaseType _dbType { get; set; }
        public BaseRepository(GeneralDbContext context)
        {
            _dbContext = context;
            _dbSet = _dbContext.Set<TEntity>();
        }
        public DatabaseFacade Database => _dbContext.Database;
        public IQueryable<TEntity> Entities => _dbSet.AsQueryable().AsNoTracking();
        public int SaveChanges()
        {
            return _dbContext.SaveChanges();
        }
        public async Task<int> SaveChangesAsync()
        {
            return await _dbContext.SaveChangesAsync();
        }
        public bool Any(Expression<Func<TEntity, bool>> whereLambd)
        {
            return _dbSet.Where(whereLambd).Any();
        }
        #region 插入數據
        public bool Insert(TEntity entity, bool isSaveChange = true)
        {
            _dbSet.Add(entity);
            if (isSaveChange)
            {
                return SaveChanges() > 0;
            }
            return false;
        }
        public async Task<bool> InsertAsync(TEntity entity, bool isSaveChange = true)
        {
            _dbSet.Add(entity);
            if (isSaveChange)
            {
                return await SaveChangesAsync() > 0;
            }
            return false;
        }
        public bool Insert(List<TEntity> entitys, bool isSaveChange = true)
        {
            _dbSet.AddRange(entitys);
            if (isSaveChange)
            {
                return SaveChanges() > 0;
            }
            return false;
        }
        public async Task<bool> InsertAsync(List<TEntity> entitys, bool isSaveChange = true)
        {
            _dbSet.AddRange(entitys);
            if (isSaveChange)
            {
                return await SaveChangesAsync() > 0;
            }
            return false;
        }
        #endregion

        #region 刪除
        public bool Delete(TEntity entity, bool isSaveChange = true)
        {
            _dbSet.Attach(entity);
            _dbSet.Remove(entity);
            return isSaveChange ? SaveChanges() > 0 : false;
        }
        public bool Delete(List<TEntity> entitys, bool isSaveChange = true)
        {
            entitys.ForEach(entity =>
            {
                _dbSet.Attach(entity);
                _dbSet.Remove(entity);
            });
            return isSaveChange ? SaveChanges() > 0 : false;
        }

        public virtual async Task<bool> DeleteAsync(TEntity entity, bool isSaveChange = true)
        {

            _dbSet.Attach(entity);
            _dbSet.Remove(entity);
            return isSaveChange ? await SaveChangesAsync() > 0 : false;
        }
        public virtual async Task<bool> DeleteAsync(List<TEntity> entitys, bool isSaveChange = true)
        {
            entitys.ForEach(entity =>
            {
                _dbSet.Attach(entity);
                _dbSet.Remove(entity);
            });
            return isSaveChange ? await SaveChangesAsync() > 0 : false;
        }
        #endregion

        #region 更新數據
        public bool Update(TEntity entity, bool isSaveChange = true, List<string> updatePropertyList = null)
        {
            if (entity == null)
            {
                return false;
            }
            _dbSet.Attach(entity);
            var entry = _dbContext.Entry(entity);
            if (updatePropertyList == null)
            {
                entry.State = EntityState.Modified;//全欄位更新
            }
            else
            {
               
                    updatePropertyList.ForEach(c => {
                        entry.Property(c).IsModified = true; //部分欄位更新的寫法
                    });
               
               
            }
            if (isSaveChange)
            {
                return SaveChanges() > 0;
            }
            return false;
        }
        public bool Update(List<TEntity> entitys, bool isSaveChange = true)
        {
            if (entitys == null || entitys.Count == 0)
            {
                return false;
            }
            entitys.ForEach(c => {
                Update(c, false);
            });
            if (isSaveChange)
            {
                return SaveChanges() > 0;
            }
            return false;
        }
        public async Task<bool> UpdateAsync(TEntity entity, bool isSaveChange = true, List<string> updatePropertyList = null)
        {
            if (entity == null)
            {
                return false;
            }
            _dbSet.Attach(entity);
            var entry = _dbContext.Entry<TEntity>(entity);
            if (updatePropertyList == null)
            {
                entry.State = EntityState.Modified;//全欄位更新
            }
            else
            {
                updatePropertyList.ForEach(c => {
                        entry.Property(c).IsModified = true; //部分欄位更新的寫法
                    });
              
            }
            if (isSaveChange)
            {
                return await SaveChangesAsync() > 0;
            }
            return false;
        }
        public async Task<bool> UpdateAsync(List<TEntity> entitys, bool isSaveChange = true)
        {
            if (entitys == null || entitys.Count == 0)
            {
                return false;
            }
            entitys.ForEach(c => {
                _dbSet.Attach(c);
                _dbContext.Entry<TEntity>(c).State = EntityState.Modified;
            });
            if (isSaveChange)
            {
                return await SaveChangesAsync() > 0;
            }
            return false;
        }




     
       
        #endregion

        #region 查找
        public long Count(Expression<Func<TEntity, bool>> predicate = null)
        {
            if (predicate == null)
            {
                predicate = c => true;
            }
            return _dbSet.LongCount(predicate);
        }
        public async Task<long> CountAsync(Expression<Func<TEntity, bool>> predicate = null)
        {
            if (predicate == null)
            {
                predicate = c => true;
            }
            return await _dbSet.LongCountAsync(predicate);
        }
        public TEntity Get(TKey id)
        {
            if (id == null)
            {
                return default(TEntity);
            }
            return _dbSet.Find(id);
        }
      
        public TEntity Get(Expression<Func<TEntity, bool>> predicate = null, bool isNoTracking = true)
        {
            var data = isNoTracking ? _dbSet.Where(predicate).AsNoTracking() : _dbSet.Where(predicate);
            return data.FirstOrDefault();
        }


        public async Task<TEntity> GetAsync(TKey id)
        {
            if (id == null)
            {
                return default(TEntity);
            }
            return await _dbSet.FindAsync(id);
        }
        public async Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> predicate = null, bool isNoTracking = true)
        {
            var data = isNoTracking ? _dbSet.Where(predicate).AsNoTracking() : _dbSet.Where(predicate);
            return await data.FirstOrDefaultAsync();
        }

       
        public async Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate = null, string ordering = "", bool isNoTracking = true)
        {
            var data = isNoTracking ? _dbSet.Where(predicate).AsNoTracking() : _dbSet.Where(predicate);
            if (!string.IsNullOrEmpty(ordering))
            {
                data = data.OrderByBatch(ordering);
            }
            return await data.ToListAsync();
        }
        public List<TEntity> GetList(Expression<Func<TEntity, bool>> predicate = null, string ordering = "", bool isNoTracking = true)
        {
            var data = isNoTracking ? _dbSet.Where(predicate).AsNoTracking() : _dbSet.Where(predicate);
            if (!string.IsNullOrEmpty(ordering))
            {
                data = data.OrderByBatch(ordering);
            }
            return data.ToList();
        }
        public async Task<IQueryable<TEntity>> LoadAsync(Expression<Func<TEntity, bool>> predicate = null, bool isNoTracking = true)
        {
            if (predicate == null)
            {
                predicate = c => true;
            }
            return await Task.Run(() => isNoTracking ? _dbSet.Where(predicate).AsNoTracking() : _dbSet.Where(predicate));
        }
        public IQueryable<TEntity> Load(Expression<Func<TEntity, bool>> predicate = null, bool isNoTracking = true)
        {
            if (predicate == null)
            {
                predicate = c => true;
            }
            return isNoTracking ? _dbSet.Where(predicate).AsNoTracking() : _dbSet.Where(predicate);
        }








        #endregion

        #region SQL語句
        public virtual void BulkInsert<T>(List<T> entities)
        { }
        public int ExecuteSql(string sql)
        {
            return _dbContext.Database.ExecuteSqlCommand(sql) ; 
        }

        public Task<int> ExecuteSqlAsync(string sql)
        {
             return _dbContext.Database.ExecuteSqlCommandAsync(sql);  
        }

        public int ExecuteSql(string sql, List<DbParameter> spList)
        {
           return  _dbContext.Database.ExecuteSqlCommand(sql, spList.ToArray());
        }

        public Task<int>  ExecuteSqlAsync(string sql, List<DbParameter> spList)
        {   
             return  _dbContext.Database.ExecuteSqlCommandAsync(sql, spList.ToArray());
        }

      
        public virtual DataTable GetDataTableWithSql(string sql)
        {
            throw new NotImplementedException();
        }

        public virtual DataTable GetDataTableWithSql(string sql, List<DbParameter> spList)
        {
            throw new NotImplementedException();
        }

        #endregion

  三、BaseRepository是個抽象類,有些比較複雜的sql語句通過EF來處理比較麻煩,還需要直接操作sql語句的方法,因不同的資料庫sql語句不一樣,針對不同的數據,繼承BaseRepository這個基類,重寫sql語句方法,下麵簡單實現SqlServerRepository倉儲

 public   class SqlServerRepository<TEntity,TKey>: BaseRepository<TEntity,TKey>,IRepository<TEntity,TKey> where TEntity : class
    {
          protected ConfigOption _dbOpion;
        public SqlServerRepository(GeneralDbContext generalDbContext,IOptionsSnapshot<ConfigOption> options)
            :base(generalDbContext)
        {     
            _dbOpion = options.Get("config");
            _connectionString = _dbOpion.ReadWriteHosts;
        }

        #region 插入數據

        /// <summary>
        /// 使用Bulk批量插入數據(適合大數據量,速度非常快)
        /// </summary>
        /// <typeparam name="T">實體類型</typeparam>
        /// <param name="entities">數據</param>
        public override void BulkInsert<T>(List<T> entities)
        {
            using (SqlConnection conn = new SqlConnection())
            {
                conn.ConnectionString =_connectionString ;
                if (conn.State != ConnectionState.Open)
                {
                    conn.Open();
                }

                string tableName = string.Empty;
                var tableAttribute = typeof(T).GetCustomAttributes(typeof(TableAttribute), true).FirstOrDefault();
                if (tableAttribute != null)
                    tableName = ((TableAttribute)tableAttribute).Name;
                else
                    tableName = typeof(T).Name;

                SqlBulkCopy sqlBC = new SqlBulkCopy(conn)
                {
                    BatchSize = 100000,
                    BulkCopyTimeout = 0,
                    DestinationTableName = tableName
                };
                using (sqlBC)
                {
                    sqlBC.WriteToServer(entities.ToDataTable());
                }
            }
        }    
      
        public override DataTable GetDataTableWithSql(string sql)
        {
            return   GetDataTableWithSql(sql);
        }

        public override DataTable GetDataTableWithSql(string sql, List<DbParameter> spList=null)
        {
            DataTable dt = new DataTable(); ;
            using (SqlConnection conn = new SqlConnection(_connectionString))
            {
                SqlDataAdapter da = new SqlDataAdapter(sql, conn);
                da.SelectCommand.CommandType = CommandType.Text;
                if (spList.ToArray() != null)
                {
                    da.SelectCommand.Parameters.AddRange(spList.ToArray());
                }
                da.Fill(dt);
            }
            return dt;
        }
        #endregion
    }

  引用了http://www.cnblogs.com/coldairarrow/p/9626691.html該框架設計思想及部分代碼


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 以C#訪問MySQL資料庫,執行簡單的CRUD。 MySql.Data.dll是C#操作MySQL的驅動文件,是C#連接MySQL必要插件,使C#語言更簡潔的操作MySQL資料庫。可以用NuGet命令安裝 PM>Install-Package MySql.Data -Version 8.0.16 項 ...
  • 每個新技術許可權驗證都有一套機制,之前項目WebApi介面許可權驗證用的是Owin做為許可權驗證,而.netcore許可權限制使用的是IdentityServer4,採用JWT的方法驗證token. 首先使用Guget包管理添加IdentityServer4包的引用,如圖 生成token方法 創建JwtTo ...
  • 串口掃描槍的簡單實現 基於串口通訊的掃描槍的實現,主要藉助SerialPort類,表示串列埠資源。實現很簡單: 工具:usb轉RS232轉接頭/個,掃描槍/套, 掃描槍串口接入轉接頭,轉接頭插電腦 接下來具體代碼實現 1 using System; 2 using System.Collectio ...
  • 如下圖,在憑證編輯窗體中,有的單元格不需要數字,但如果錄入數字後再刪除,會觸發數字驗證,單元格顯示紅色框線,導致不能執行其他操作。 Xaml代碼如下: 解決思路是用轉換器Converter代替StringFormat: Xmal主要代碼: C#主要代碼: ...
  • DataGrid中數據顯示如下圖,數據格式比較雜亂。希望達到以下要求:(1)所有數據保留兩位小數;(2)超過1000的數字顯示千分位;(3)如果數據為0,不顯示。 首先想到用StringFormat進行格式化: 效果如下圖,希望實現的要求(1)和(2)達到了,但(3)如果數據為0,不顯示的要求沒有達 ...
  • 在前面大致講了設計模式六大原則及三大模型(行為型、創建型、結構型)23種設模式;本文講模版方法屬於行為型模式; 模版方法:簡單講是定了一個演算法骨架,將可變的部分延遲到了子類,由子類來實現,封裝不可變的,也是一種多態的實現; 有這樣的一個場景:需要對數據進行CURD操作,且能支持不同的資料庫操作,我們 ...
  • 1. 獲取瀏覽器信息 2. IE 瀏覽器訪問頁面時 3. FireFox 瀏覽器訪問頁面時 ...
  • .Net平臺下相容.NET Standard 2.0,一個實現以Lambda表達式轉轉換標準SQL語句,支持MySQL、SQL Server資料庫方言,使用強類型操作數據的輕量級ORM工具,在減少魔法字串同時,通過靈活的Lambda表達式組合,實現業務數據查詢的多樣性。 如果想找到替代EF方案,Sq... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...