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

来源: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
更多相關文章
  • 目前Web開發,大部分公司都用的是前後端分離模式,即前端專註於前端頁面交互,後端專註於功能實現及提供Web Api介面。 在某次新站點的開發過程中,為了網站的安全性,要求Web站點使用https協議,在部署到QA環境時,發現調用介面報如下的錯: 從提示的內容來看,大致可推斷出是因為站點是https協 ...
  • 前言 解析Excel有知名的NPOI庫,(Java語言是POI),但是NPOI是不支持解析csv的。 csv本質上也是文本文件,可以進行差異對比,更利於解決衝突。 本文對解析csv的幾個.net的開源庫進行調研 很小巧簡單的庫:https://github.com/stevehansen/csv/ ...
  • RabbitMQ配置環境花費了好多時間,特記錄此筆記,方便下次部署安裝。筆記中將常見的安裝錯誤問題、解決辦法與安裝過程一同展示。 ...
  • 第一次寫隨筆 應該寫的不是太好 請多多見諒 我這次是在網上發現了一個三級聯動 也是給新人一個福利 這個是你需要新建個 JavaScript 文件 並複製到你新建的文件裡面 1 var provinces = [ 2 { 3 "name": "北京市", 4 "city": [ 5 { 6 "name ...
  • 環境 本地 win7 伺服器:Virtual Box 上的Centos ssh工具: Xshell 文件傳輸: xftp 1.在本地創建asp.net core應用發佈 1.1 使用Vs2017 新建一個asp.netcore項目 步驟略(一路next),當然你也可以用命令行創建。 1.2 發佈項目 ...
  • 列印預覽XAML代碼: <controls:WindowEx x:Class="SunCreate.Vipf.Client.UI.MapPrintPreview" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xm ...
  • 之前有寫過c#區域網桌面共用軟體製作(https://www.cnblogs.com/liuxiaobo93/p/3675387.html),完成了一個簡易的點對點的桌面共用demo,使用的就是Tcp協議,當時由於接收端接收數據用了一個比較大的byte數組來一次性接收完整張圖片數據,所以有人提出了問... ...
  • DncZeus 前言 關於 DncZeus DncZeus = Dnc + Zeus "Dnc" .Net Core 的縮寫; "Zeus" 中文譯為 宙斯 ,是古希臘神話中的眾神之王,奧林匹斯十二主神之首,統治宇宙萬物的至高無上的主神(在古希臘神話中主神專指宙斯),人們常用“眾神和人類的父親”、“ ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...