.NET Core實戰項目之CMS 第十二章 開發篇-Dapper封裝GURD及倉儲代碼生成器實現

来源:https://www.cnblogs.com/yilezhu/archive/2018/12/19/10146311.html
-Advertisement-
Play Games

本篇我將帶著大家一起來對Dapper進行下封裝並實現基本的增刪改查、分頁操作的同步非同步方法的實現(已實現MSSQL,MySql,PgSQL)。同時我們再實現一下倉儲層的代碼生成器,這樣的話,我們只需要結合業務來實現具體的業務部分的代碼就可以了,可以大大減少我們重覆而又繁瑣的增刪改查操作,多留點時間給 ...


本篇我將帶著大家一起來對Dapper進行下封裝並實現基本的增刪改查、分頁操作的同步非同步方法的實現(已實現MSSQL,MySql,PgSQL)。同時我們再實現一下倉儲層的代碼生成器,這樣的話,我們只需要結合業務來實現具體的業務部分的代碼就可以了,可以大大減少我們重覆而又繁瑣的增刪改查操作,多留點時間給生活充充電(不會偷懶的程式員不是一位好爸爸/好老公/好男朋友)。如果您覺得我的實現過程有所不妥的話,您可以在評論區留言,或者加入我們的千人.Net Core實戰項目交流群637326624交流。另外如果您覺得我的文章對您有所幫助的話希望給個推薦以示支持。項目的源代碼我會托管在GayHub上,地址在文章末尾會給出,自認為代碼寫的很工整,註釋也很全,你應該能看懂!

本文已收錄至《.NET Core實戰項目之CMS 第一章 入門篇-開篇及總體規劃

作者:依樂祝

原文地址:https://www.cnblogs.com/yilezhu/p/10146311.html

寫在前面

將近一周沒有更新,鬼知道我這麼長時間在乾什麼,你可以認為我在憋大招,在想著怎麼給大家分享更多更實用的東西。其實這隻是我偷懶的藉口罷了!下麵我們一起來對Dapper進行下封裝吧,然後結合Dapper.SimpleCRUD 來實現基本的增刪改查、分頁操作。這部分功能實現完成後,往下我們也就是基於這些基本操作來實現我們的CMS的業務了,如:許可權部分,菜單部分,文章部分的功能。接下來我會對這部分快速的實現,可能會很少更新了,因為這些都是基本的CMS的業務操作,沒多少要分享的內容,畢竟每個人的系統業務都不一樣,這部分的業務實現也是千差萬別的。我後期會把成品直接分享給大家!敬請關註吧!

Dapper的封裝

IDbConnection工廠類的封裝

這部分我實現了一個IDbConnection的工廠類,以便你可以很方便的根據資料庫的類型來創建不同的IDbConnection對象,目前已實現對SqlServer,MySQL,PostgreSQL的實現,具體代碼如下,根據傳入的參數來進行相關的實現。

       /// <summary>
    /// yilezhu
    /// 2018.12.13
    /// 資料庫連接工廠類
    /// </summary>
    public class ConnectionFactory
    {
        /// <summary>
        /// 獲取資料庫連接
        /// </summary>
        /// <param name="dbtype">資料庫類型</param>
        /// <param name="conStr">資料庫連接字元串</param>
        /// <returns>資料庫連接</returns>
        public static IDbConnection CreateConnection(string dbtype, string strConn)
        {
            if (dbtype.IsNullOrWhiteSpace())
                throw new ArgumentNullException("獲取資料庫連接居然不傳資料庫類型,你想上天嗎?");
            if (strConn.IsNullOrWhiteSpace())
                throw new ArgumentNullException("獲取資料庫連接居然不傳資料庫類型,你想上天嗎?");
            var dbType = GetDataBaseType(dbtype);
            return CreateConnection(dbType,strConn);
        }

        /// <summary>
        /// 獲取資料庫連接
        /// </summary>
        /// <param name="dbType">資料庫類型</param>
        /// <param name="conStr">資料庫連接字元串</param>
        /// <returns>資料庫連接</returns>
        public static IDbConnection CreateConnection(DatabaseType dbType, string strConn)
        {
            IDbConnection connection = null;           
            if (strConn.IsNullOrWhiteSpace())
                throw new ArgumentNullException("獲取資料庫連接居然不傳資料庫類型,你想上天嗎?");
            
            switch (dbType)
            {
                case DatabaseType.SqlServer:
                    connection = new SqlConnection(strConn);
                    break;
                case DatabaseType.MySQL:
                    connection = new MySqlConnection(strConn);
                    break;
                case DatabaseType.PostgreSQL:
                    connection = new NpgsqlConnection(strConn);
                    break;
                default:
                    throw new ArgumentNullException($"這是我的錯,還不支持的{dbType.ToString()}資料庫類型");

            }
            if (connection.State == ConnectionState.Closed)
            {
                connection.Open();
            }
            return connection;
        }

        /// <summary>
        /// 轉換資料庫類型
        /// </summary>
        /// <param name="dbtype">資料庫類型字元串</param>
        /// <returns>資料庫類型</returns>
        public static DatabaseType GetDataBaseType(string dbtype)
        {
            if (dbtype.IsNullOrWhiteSpace())
                throw new ArgumentNullException("獲取資料庫連接居然不傳資料庫類型,你想上天嗎?");
            DatabaseType returnValue = DatabaseType.SqlServer;
            foreach (DatabaseType dbType in Enum.GetValues(typeof(DatabaseType)))
            {
                if (dbType.ToString().Equals(dbtype, StringComparison.OrdinalIgnoreCase))
                {
                    returnValue = dbType;
                    break;
                }
            }
            return returnValue;
        }

        
    }

那麼,我們怎麼來使用這個工廠類呢?如下給出調用的實例。

1545221995138

是不是很簡單,感覺瞬間少了很多代碼,這段代碼摘錄自代碼生成器裡面。有興趣的自己去查看源碼吧!

CRUD及分頁泛型方法的實現

  1. nuget安裝Dapper.SimpleCRUD ,什麼你要問我怎麼安裝?乖乖的回去看第二篇文章吧!那裡會教你如何安裝Nuget包?如果那篇文章裡面沒有,那你就好好想想為啥沒有呢?

    1545222273003

  2. 新建IBaseRepository泛型介面 定義如下的增刪改查方法的同步非同步介面,其中還包含分頁的實現,具體的代碼如下:

    /**
    *┌──────────────────────────────────────────────────────────────┐
    *│ 描    述:                                                    
    *│ 作    者:yilezhu                                             
    *│ 版    本:1.0                                                 
    *│ 創建時間:2018/12/16 20:41:22                             
    *└──────────────────────────────────────────────────────────────┘
    *┌──────────────────────────────────────────────────────────────┐
    *│ 命名空間: Czar.Cms.Core.Repository                                   
    *│ 介面名稱: IBaseRepository                                      
    *└──────────────────────────────────────────────────────────────┘
    */
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Czar.Cms.Core.Repository
    {
        public interface IBaseRepository<T,TKey> :  IDisposable where T : class
        {
            #region 同步
            /// <summary>
            /// 通過主鍵獲取實體對象
            /// </summary>
            /// <param name="id">主鍵ID</param>
            /// <returns></returns>
            T Get(TKey id);
            /// <summary>
            /// 獲取所有的數據
            /// </summary>
            /// <returns></returns>
            IEnumerable<T> GetList();
            /// <summary>
            /// 執行具有條件的查詢,並將結果映射到強類型列表
            /// </summary>
            /// <param name="whereConditions">條件</param>
            /// <returns></returns>
            IEnumerable<T> GetList(object whereConditions);
            /// <summary>
            /// 帶參數的查詢滿足條件的數據
            /// </summary>
            /// <param name="conditions">條件</param>
            /// <param name="parameters">參數</param>
            /// <returns></returns>
            IEnumerable<T> GetList(string conditions, object parameters = null);
            /// <summary>
            /// 使用where子句執行查詢,並將結果映射到具有Paging的強類型List
            /// </summary>
            /// <param name="pageNumber">頁碼</param>
            /// <param name="rowsPerPage">每頁顯示數據</param>
            /// <param name="conditions">查詢條件</param>
            /// <param name="orderby">排序</param>
            /// <param name="parameters">參數</param>
            /// <returns></returns>
            IEnumerable<T> GetListPaged(int pageNumber, int rowsPerPage, string conditions, string orderby, object parameters = null);
            /// <summary>
            /// 插入一條記錄並返回主鍵值(自增類型返回主鍵值,否則返回null)
            /// </summary>
            /// <param name="entity"></param>
            /// <returns></returns>
            int? Insert(T entity);
            /// <summary>
            /// 更新一條數據並返回影響的行數
            /// </summary>
            /// <param name="entity"></param>
            /// <returns>影響的行數</returns>
            int Update(T entity);
            /// <summary>
            /// 根據實體主鍵刪除一條數據
            /// </summary>
            /// <param name="id">主鍵</param>
            /// <returns>影響的行數</returns>
            int Delete(TKey id);
            /// <summary>
            /// 根據實體刪除一條數據
            /// </summary>
            /// <param name="entity">實體</param>
            /// <returns>返回影響的行數</returns>
            int Delete(T entity);
            /// <summary>
            /// 條件刪除多條記錄
            /// </summary>
            /// <param name="whereConditions">條件</param>
            /// <param name="transaction">事務</param>
            /// <param name="commandTimeout">超時時間</param>
            /// <returns>影響的行數</returns>
            int DeleteList(object whereConditions, IDbTransaction transaction = null, int? commandTimeout = null);
            /// <summary>
            /// 使用where子句刪除多個記錄
            /// </summary>
            /// <param name="conditions">wher子句</param>
            /// <param name="parameters">參數</param>
            /// <param name="transaction">事務</param>
            /// <param name="commandTimeout">超時時間</param>
            /// <returns>影響的行數</returns>
            int DeleteList(string conditions, object parameters = null, IDbTransaction transaction = null, int? commandTimeout = null);
            /// <summary>
            /// 滿足條件的記錄數量
            /// </summary>
            /// <param name="conditions"></param>
            /// <param name="parameters"></param>
            /// <returns></returns>
            int RecordCount(string conditions = "", object parameters = null);
            #endregion
            #region 非同步
            /// <summary>
            /// 通過主鍵獲取實體對象
            /// </summary>
            /// <param name="id">主鍵ID</param>
            /// <returns></returns>
            Task<T> GetAsync(TKey id);
            /// <summary>
            /// 獲取所有的數據
            /// </summary>
            /// <returns></returns>
            Task<IEnumerable<T>> GetListAsync();
            /// <summary>
            /// 執行具有條件的查詢,並將結果映射到強類型列表
            /// </summary>
            /// <param name="whereConditions">條件</param>
            /// <returns></returns>
            Task<IEnumerable<T>> GetListAsync(object whereConditions);
            /// <summary>
            /// 帶參數的查詢滿足條件的數據
            /// </summary>
            /// <param name="conditions">條件</param>
            /// <param name="parameters">參數</param>
            /// <returns></returns>
            Task<IEnumerable<T>> GetListAsync(string conditions, object parameters = null);
            /// <summary>
            /// 使用where子句執行查詢,並將結果映射到具有Paging的強類型List
            /// </summary>
            /// <param name="pageNumber">頁碼</param>
            /// <param name="rowsPerPage">每頁顯示數據</param>
            /// <param name="conditions">查詢條件</param>
            /// <param name="orderby">排序</param>
            /// <param name="parameters">參數</param>
            /// <returns></returns>
            Task<IEnumerable<T>> GetListPagedAsync(int pageNumber, int rowsPerPage, string conditions, string orderby, object parameters = null);
            /// <summary>
            /// 插入一條記錄並返回主鍵值
            /// </summary>
            /// <param name="entity"></param>
            /// <returns></returns>
            Task<int?> InsertAsync(T entity);
            /// <summary>
            /// 更新一條數據並返回影響的行數
            /// </summary>
            /// <param name="entity"></param>
            /// <returns>影響的行數</returns>
            Task<int> UpdateAsync(T entity);
            /// <summary>
            /// 根據實體主鍵刪除一條數據
            /// </summary>
            /// <param name="id">主鍵</param>
            /// <returns>影響的行數</returns>
            Task<int> DeleteAsync(TKey id);
            /// <summary>
            /// 根據實體刪除一條數據
            /// </summary>
            /// <param name="entity">實體</param>
            /// <returns>返回影響的行數</returns>
            Task<int> DeleteAsync(T entity);
            /// <summary>
            /// 條件刪除多條記錄
            /// </summary>
            /// <param name="whereConditions">條件</param>
            /// <param name="transaction">事務</param>
            /// <param name="commandTimeout">超時時間</param>
            /// <returns>影響的行數</returns>
            Task<int> DeleteListAsync(object whereConditions, IDbTransaction transaction = null, int? commandTimeout = null);
            /// <summary>
            /// 使用where子句刪除多個記錄
            /// </summary>
            /// <param name="conditions">wher子句</param>
            /// <param name="parameters">參數</param>
            /// <param name="transaction">事務</param>
            /// <param name="commandTimeout">超時時間</param>
            /// <returns>影響的行數</returns>
            Task<int> DeleteListAsync(string conditions, object parameters = null, IDbTransaction transaction = null, int? commandTimeout = null);
            /// <summary>
            /// 滿足條件的記錄數量
            /// </summary>
            /// <param name="conditions"></param>
            /// <param name="parameters"></param>
            /// <returns></returns>
            Task<int> RecordCountAsync(string conditions = "", object parameters = null);
            #endregion
        }
    }
    
  3. 然後創建一個BaseRepository泛型類來實現上面的介面,其中多了兩個成員,DbOpion以及IDbConnection,猜猜看這兩個東西有什麼用?後面給出答案

    /**
    *┌──────────────────────────────────────────────────────────────┐
    *│ 描    述:倉儲類的基類                                                    
    *│ 作    者:yilezhu                                             
    *│ 版    本:1.0                                                 
    *│ 創建時間:2018/12/16 12:03:02                             
    *└──────────────────────────────────────────────────────────────┘
    *┌──────────────────────────────────────────────────────────────┐
    *│ 命名空間: Czar.Cms.Core.Repository                                   
    *│ 類    名: BaseRepository                                      
    *└──────────────────────────────────────────────────────────────┘
    */
    using Czar.Cms.Core.DbHelper;
    using Czar.Cms.Core.Options;
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Text;
    using System.Threading.Tasks;
    using Dapper;
    
    namespace Czar.Cms.Core.Repository
    {
        public class BaseRepository<T, TKey> : IBaseRepository<T, TKey> where T : class
        {
            protected DbOpion _dbOpion;
            protected IDbConnection _dbConnection;
    
            //public BaseRepository(DbOpion dbOpion)
            //{
            //    _dbOpion = dbOpion ?? throw new ArgumentNullException(nameof(DbOpion));
            //    _dbConnection = ConnectionFactory.CreateConnection(_dbOpion.DbType, _dbOpion.ConnectionString);
            //}
    
            #region 同步
    
            public T Get(TKey id) => _dbConnection.Get<T>(id);
            public IEnumerable<T> GetList() => _dbConnection.GetList<T>();
    
            public IEnumerable<T> GetList(object whereConditions) => _dbConnection.GetList<T>(whereConditions);
    
            public IEnumerable<T> GetList(string conditions, object parameters = null) => _dbConnection.GetList<T>(conditions, parameters);
    
            public IEnumerable<T> GetListPaged(int pageNumber, int rowsPerPage, string conditions, string orderby, object parameters = null)
            {
                return _dbConnection.GetListPaged<T>(pageNumber, rowsPerPage, conditions, orderby, parameters);
            }
            public int? Insert(T entity) => _dbConnection.Insert(entity);
            public int Update(T entity) => _dbConnection.Update(entity);
    
            public int Delete(TKey id) => _dbConnection.Delete<T>(id);
    
            public int Delete(T entity) => _dbConnection.Delete(entity);
            public int DeleteList(object whereConditions, IDbTransaction transaction = null, int? commandTimeout = null)
            {
                return _dbConnection.DeleteList<T>(whereConditions, transaction, commandTimeout);
            }
    
            public int DeleteList(string conditions, object parameters = null, IDbTransaction transaction = null, int? commandTimeout = null)
            {
                return _dbConnection.DeleteList<T>(conditions, parameters, transaction, commandTimeout);
            }
            public int RecordCount(string conditions = "", object parameters = null)
            {
                return _dbConnection.RecordCount<T>(conditions, parameters);
            }
            #endregion
    
            #region 非同步
            public async Task<T> GetAsync(TKey id)
            {
                return await _dbConnection.GetAsync<T>(id);
            }
    
            public async Task<IEnumerable<T>> GetListAsync()
            {
                return await _dbConnection.GetListAsync<T>();
            }
    
            public async Task<IEnumerable<T>> GetListAsync(object whereConditions)
            {
                return await _dbConnection.GetListAsync<T>(whereConditions);
            }
    
            public async Task<IEnumerable<T>> GetListAsync(string conditions, object parameters = null)
            {
                return await _dbConnection.GetListAsync<T>(conditions, parameters);
            }
            public async Task<IEnumerable<T>> GetListPagedAsync(int pageNumber, int rowsPerPage, string conditions, string orderby, object parameters = null)
            {
                return await _dbConnection.GetListPagedAsync<T>(pageNumber, rowsPerPage, conditions, orderby, parameters);
            }
            public async Task<int?> InsertAsync(T entity)
            {
                return await _dbConnection.InsertAsync(entity);
            }
            public async Task<int> UpdateAsync(T entity)
            {
                return await _dbConnection.UpdateAsync(entity);
            }
            public async Task<int> DeleteAsync(TKey id)
            {
                return await _dbConnection.DeleteAsync(id);
            }
    
            public async Task<int> DeleteAsync(T entity)
            {
                return await _dbConnection.DeleteAsync(entity);
            }
    
    
            public async Task<int> DeleteListAsync(object whereConditions, IDbTransaction transaction = null, int? commandTimeout = null)
            {
                return await _dbConnection.DeleteListAsync<T>(whereConditions, transaction, commandTimeout);
            }
    
            public async Task<int> DeleteListAsync(string conditions, object parameters = null, IDbTransaction transaction = null, int? commandTimeout = null)
            {
                return await DeleteListAsync(conditions, parameters, transaction, commandTimeout);
            }
            public async Task<int> RecordCountAsync(string conditions = "", object parameters = null)
            {
                return await _dbConnection.RecordCountAsync<T>(conditions, parameters);
            }
            #endregion
    
            #region IDisposable Support
            private bool disposedValue = false; // 要檢測冗餘調用
    
            protected virtual void Dispose(bool disposing)
            {
                if (!disposedValue)
                {
                    if (disposing)
                    {
                        // TODO: 釋放托管狀態(托管對象)。
                    }
    
                    // TODO: 釋放未托管的資源(未托管的對象)併在以下內容中替代終結器。
                    // TODO: 將大型欄位設置為 null。
    
                    disposedValue = true;
                }
            }
    
            // TODO: 僅當以上 Dispose(bool disposing) 擁有用於釋放未托管資源的代碼時才替代終結器。
            // ~BaseRepository() {
            //   // 請勿更改此代碼。將清理代碼放入以上 Dispose(bool disposing) 中。
            //   Dispose(false);
            // }
    
            // 添加此代碼以正確實現可處置模式。
            public void Dispose()
            {
                // 請勿更改此代碼。將清理代碼放入以上 Dispose(bool disposing) 中。
                Dispose(true);
                // TODO: 如果在以上內容中替代了終結器,則取消註釋以下行。
                // GC.SuppressFinalize(this);
            }
            #endregion
        }
    }
    

    你沒看錯?我在16號就已經寫好了,為什麼這麼晚才寫博客分享出來呢?因為我懶~~~~~~~

  4. 這裡需要註意,需要安裝SimpleCRUD的Nuget包。另外其他的倉儲方法只需要繼承這個介面以及實現就能夠實現基本的增刪改查操作了。這裡你應該會想,既然繼承就能實現,那何不寫一個倉儲的代碼生成器來進行生成呢?說乾就乾,下麵我們就來實現倉儲的代碼生成器

倉儲層代碼生成器

上篇生成資料庫實體的代碼生成器不知道大家看了沒有,這裡我們只需要在根據每個資料庫表生成資料庫實體的實體順帶著生成下倉儲介面以及倉儲代碼就可以了。有了思路,我們就擼起袖子加油乾吧

  1. 先寫一下倉儲介面代碼生成器的模板,如下所示:

    1545225197161

  2. 再寫一下倉儲層的代碼實現,這裡需要註意一下,需要根據註入的IOptionsSnapshot來生成_dbOpion以及_dbConnection,上面留給大家的思考題答案就在這裡,如下所示:

    /**
    *┌──────────────────────────────────────────────────────────────┐
    *│ 描    述:{Comment}介面實現                                                    
    *│ 作    者:{Author}                                            
    *│ 版    本:1.0    模板代碼自動生成                                                
    *│ 創建時間:{GeneratorTime}                             
    *└──────────────────────────────────────────────────────────────┘
    *┌──────────────────────────────────────────────────────────────┐
    *│ 命名空間: {RepositoryNamespace}                                  
    *│ 類    名: {ModelName}Repository                                      
    *└──────────────────────────────────────────────────────────────┘
    */
    using Czar.Cms.Core.DbHelper;
    using Czar.Cms.Core.Options;
    using Czar.Cms.Core.Repository;
    using Czar.Cms.IRepository;
    using Czar.Cms.Models;
    using Microsoft.Extensions.Options;
    using System;
    
    namespace {RepositoryNamespace}
    {
        public class {ModelName}Repository:BaseRepository<{ModelName},{KeyTypeName}>, I{ModelName}Repository
        {
            public {ModelName}Repository(IOptionsSnapshot<DbOpion> options)
            {
                _dbOpion =options.Get("CzarCms");
                if (_dbOpion == null)
                {
                    throw new ArgumentNullException(nameof(DbOpion));
                }
                _dbConnection = ConnectionFactory.CreateConnection(_dbOpion.DbType, _dbOpion.ConnectionString);
            }
    
        }
    }
  3. 接著就是代碼生成器生成IRepository以及生成Repository的代碼了!這部分代碼如下圖所示:

    1545225567381

    1545225578141

測試代碼

  1. 重新執行下代碼生成器的代碼,測試的具體代碼我已經放在GitHub上了,這裡就不貼出來了,直接上生成結果如下圖所示:

    1545225741822

  2. 如上圖所示:一次性生成了Models以及Repository,IRepository的代碼,然後到每個文件夾裡面把對應的代碼拷貝到對應的項目裡面吧。然後我們隨便打開一下倉儲以及倉儲介面看下生成後的代碼如下所示:

    /**
    *┌──────────────────────────────────────────────────────────────┐
    *│ 描    述:文章分類                                                    
    *│ 作    者:yilezhu                                              
    *│ 版    本:1.0   模板代碼自動生成                                              
    *│ 創建時間:2018-12-18 13:28:43                           
    *└──────────────────────────────────────────────────────────────┘
    *┌──────────────────────────────────────────────────────────────┐
    *│ 命名空間: Czar.Cms.IRepository                                   
    *│ 介面名稱: IArticleCategoryRepository                                      
    *└──────────────────────────────────────────────────────────────┘
    */
    using Czar.Cms.Core.Repository;
    using Czar.Cms.Models;
    using System;
    
    namespace Czar.Cms.IRepository
    {
        public interface IArticleCategoryRepository : IBaseRepository<ArticleCategory, Int32>
        {
        }
    }
    /**
    *┌──────────────────────────────────────────────────────────────┐
    *│ 描    述:文章分類介面實現                                                    
    *│ 作    者:yilezhu                                            
    *│ 版    本:1.0    模板代碼自動生成                                                
    *│ 創建時間:2018-12-18 13:28:43                             
    *└──────────────────────────────────────────────────────────────┘
    *┌──────────────────────────────────────────────────────────────┐
    *│ 命名空間: Czar.Cms.Repository.SqlServer                                  
    *│ 類    名: ArticleCategoryRepository                                      
    *└──────────────────────────────────────────────────────────────┘
    */
    using Czar.Cms.Core.DbHelper;
    using Czar.Cms.Core.Options;
    using Czar.Cms.Core.Repository;
    using Czar.Cms.IRepository;
    using Czar.Cms.Models;
    using Microsoft.Extensions.Options;
    using System;
    
    namespace Czar.Cms.Repository.SqlServer
    {
        public class ArticleCategoryRepository:BaseRepository<ArticleCategory,Int32>, IArticleCategoryRepository
        {
            public ArticleCategoryRepository(IOptionsSnapshot<DbOpion> options)
            {
                _dbOpion =options.Get("CzarCms");
                if (_dbOpion == null)
                {
                    throw new ArgumentNullException(nameof(DbOpion));
                }
                _dbConnection = ConnectionFactory.CreateConnection(_dbOpion.DbType, _dbOpion.ConnectionString);
            }
    
        }
    }
  3. 在倉儲層以及倉儲介面層添加對Czar.Cms.Core的引用,當然你也可以通過Nuget包來進行安裝

    Install-Package Czar.Cms.Core -Version 0.1.3
  4. 最後在測試代碼中進行測試,這裡以ArticleCategoryRepository為例進行測試:

    [Fact]
            public void TestBaseFactory()
            {
                IServiceProvider serviceProvider = BuildServiceForSqlServer();
                IArticleCategoryRepository categoryRepository = serviceProvider.GetService<IArticleCategoryRepository>();
                var category = new ArticleCategory
                {
                    Title = "隨筆",
                    ParentId = 0,
                    ClassList = "",
                    ClassLayer = 0,
                    Sort = 0,
                    ImageUrl = "",
                    SeoTitle = "隨筆的SEOTitle",
                    SeoKeywords = "隨筆的SeoKeywords",
                    SeoDescription = "隨筆的SeoDescription",
                    IsDeleted = false,
                };
                var categoryId = categoryRepository.Insert(category);
                var list = categoryRepository.GetList();
                Assert.True(1 == list.Count());
                Assert.Equal("隨筆", list.FirstOrDefault().Title);
                Assert.Equal("SQLServer", DatabaseType.SqlServer.ToString(), ignoreCase: true);
                categoryRepository.Delete(categoryId.Value);
                var count = categoryRepository.RecordCount();
                Assert.True(0 == count);
  5. 測試結果如下所示,都已經測試成功了:

    1545226136210

開原地址

這個系列教程的源碼我會開放在GitHub以及碼雲上,有興趣的朋友可以下載查看!覺得不錯的歡迎Star

GitHub:https://github.com/yilezhu/Czar.Cms

碼雲:https://gitee.com/yilezhu/Czar.Cms

如果你覺得這個系列對您有所幫助的話,歡迎以各種方式進行贊助,當然給個Star支持下也是可以滴!另外一種最簡單粗暴的方式就是下麵這種直接關註我們的公眾號了: img 

第一時間收到更新推送。

總結

一路走來,已經更新到第十二篇了,到這裡大伙已經可以基於這個Dapper的封裝進行自己的業務系統的開發了!當然接下來我會繼續完成我們既定的CMS系統的業務功能開發,接下來可以用來分享的東西就很少了,所以我更多的是開發然後把代碼更新到GitHub以及碼雲上,想看最新的代碼就獲取dev分支的代碼,有問題的可以提issue或者群里討論!敬請期待吧!


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

-Advertisement-
Play Games
更多相關文章
  • 1.變數名 命名規則: 在名稱中只能使用字母字元、數字和下劃線; 名稱的第一個字元不能是數字; 不能將C++關鍵詞用作名稱。 常用的首碼:n-整數,str/sz-字元串,b-布爾值,p-指針,c-單個字元,m-類成員值 2.整形 short 至少16位; int至少與short一樣長; long至少 ...
  • 1.文件讀模式 r f = open("helloworld", 'r', encoding="utf-8") 文件句柄: "helloworld" 表示讀的文件的文件名, 'r' 代表讀模式, encoding="utf-8" 表示字元編碼形式為utf-8。 有open就有close,不管是讀文件 ...
  • Python基礎知識(37):訪問資料庫(Ⅱ) 因臨近考試,本人即將進入複習階段,從明天12月19號至2019年的1月二十多號暫停更新 二、MySQL MySQL是Web世界中使用最廣泛的資料庫伺服器。SQLite的特點是輕量級、可嵌入,但不能承受高併發訪問,適合桌面和移動應用。而MySQL是為服務 ...
  • 在我們的世界中事物和事物之間總會有一些聯繫. 在面向對象中. 類和類之間也可以產生相關的關係 1. 依賴關係 執行某個動作的時候. 需要xxx來幫助你完成這個操作. 此時的關係是最輕的. 隨時可以更換另外一個東西來完成此操作 2. 關聯關係 在對象裡面埋對象 1. 一對一關係 2. 一對多關係 類中 ...
  • 本文說明瞭如何定製化JHipster-Registry,增加消息匯流排功能。 ...
  • 前言: 最近有人在Twisted郵件列表中提出諸如”為任務緊急的人提供一份Twisted介紹”的的需求。值得提前透露的是,這個序列並不會如他們所願.尤其是介紹Twisted框架和基於Python 的非同步編程而言,可能短時間無法講清楚。因此,如果你時間緊急,這恐怕不是你想找的資料。 我相信如果對非同步編 ...
  • 一、前言 瞭解過flask的python開發者想必都知道flask中核心機制莫過於上下文管理,當然學習flask如果不瞭解其中的處理流程,可能在很多問題上不能得到解決,當然我在寫本篇文章之前也看到了很多博文有關於對flask上下文管理的剖析都非常到位,當然為了學習flask我也把對flask上下文理 ...
  • 幾乎在所有的應用程式中,緩存都是一個永恆的話題,恰當的使用緩存可以有效提高應用程式的性能;在某些業務場景下,使用緩存依賴會有很好的體驗;在 Asp.Net Core 中,支持了多種緩存組件,下麵要介紹的內容就是基於 IMemoryCache 的緩存依賴。 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...