基於SqlSugar的開發框架循序漸進介紹(1)--框架基礎類的設計和使用

来源:https://www.cnblogs.com/wuhuacong/archive/2022/05/14/16269515.html
-Advertisement-
Play Games

在實際項目開發中,我們可能會碰到各種各樣的項目環境,有些項目需要一個大而全的整體框架來支撐開發,有些中小項目這需要一些簡單便捷的系統框架靈活開發。本系列隨筆介紹底層利用SqlSugar來做ORM數據訪問模塊,設計一個簡單便捷一點的框架,本篇從基礎開始介紹一些框架內容。 ...


在實際項目開發中,我們可能會碰到各種各樣的項目環境,有些項目需要一個大而全的整體框架來支撐開發,有些中小項目這需要一些簡單便捷的系統框架靈活開發。目前大型一點的框架,可以採用ABP或者ABP VNext的框架,兩者整體思路和基礎設計類似,不過ABP側重於一個獨立完整的項目框架,開發的時候統一整合處理;而ABP VNext則是以微服務架構為基礎,各個模塊獨立開發,既可以整合在一個項目中,也可以以微服務進行單獨發佈,並統一通過網關處理進行交流。不管ABP或者ABP VNext框架,都集合了.NET CORE領域眾多技術為一體,並且基礎類設計上,錯綜複雜,關係較多,因此開發學習有一定的門檻,中小型項目應用起來有一定的費勁之處。本系列隨筆介紹底層利用SqlSugar來做ORM數據訪問模塊,設計一個簡單便捷一點的框架,本篇從基礎開始介紹一些框架內容,參照一些ABP/ABP VNext中的一些類庫處理,來承載類似條件分頁信息,查詢條件處理等處理細節。

1、基於SqlSugar開發框架的架構設計

主要的設計模塊場景如下所示。

 

為了避免像ABP VNext框架那樣分散幾十個項目,我們儘可能聚合內容放在一個項目裡面。

1)其中一些常用的類庫,以及SqlSugar框架的基類放在框架公用模塊裡面。

2)Winform開發相關的基礎界面以及通用組件內容,放在基礎Winform界面庫BaseUIDx項目中。

3)基礎核心數據模塊SugarProjectCore,主要就是開發業務所需的數據處理和業務邏輯的項目,為了方便,我們區分Interface、Modal、Service三個目錄來放置不同的內容,其中Modal是SqlSugar的映射實體,Interface是定義訪問介面,Service是提供具體的數據操作實現。其中Service裡面一些框架基類和介面定義,統一也放在公用類庫裡面。

4)Winform應用模塊,主要就是針對業務開發的WInform界面應用,而WInform開發為了方便,也會將一些基礎組件和基類放在了BaseUIDx的Winform專用的界面庫裡面。

5)WebAPI項目採用基於.net Core6的項目開發,通過調用SugarProjectCore實現相關控制器API的發佈,並整合Swagger發佈介面,供其他前端界面應用進行調用。

6)純前端通過API進行調用Web API的介面,純前端模塊可以包含Vue3&Element項目,以及基於EelectronJS應用,發佈跨平臺的基於瀏覽器的應用界面,以及其他App或者小程式整合Web API進行業務數據的處理或者展示需要。

如後端開發,我們可以在VS2022中進行管理,管理開發Winform項目、Web API項目等。

Winform界面,我們可以採用基於.net Framework開發或者.net core6進行開發均可,因為我們的SugarProjectCore項目是採用.net Standard模式開發,相容兩者。這裡以許可權模塊來進行演示整合使用。

 

 而純前端的項目,我們可以基於VSCode或者 HBuilderX等工具進行項目的管理開發工作。

 

2、框架基礎類的定義和處理

在開發一個易於使用的框架的時候,主要目的就是減少代碼開發,並儘可能通過基類和泛型約束的方式,提高介面的通用性,並通過結合代碼生成工具的方式,來提高標準項目的開發效率。

那麼我們這裡基於SqlSugar的ORM處理,來實現常規數據的增刪改查等常規操作的時候,我們是如何進行這些介面的封裝處理的呢。

例如,我們對於一個簡單的客戶信息表,如下所示。

 那麼它生成的SqlSugar實體類如下所示。

    /// <summary>
    /// 客戶信息
    /// 繼承自Entity,擁有Id主鍵屬性
    /// </summary>
    [SugarTable("T_Customer")]
    public class CustomerInfo : Entity<string>
    {
        /// <summary>
        /// 預設構造函數(需要初始化屬性的在此處理)
        /// </summary>
        public CustomerInfo()
        {
            this.CreateTime = System.DateTime.Now;
        }

        #region Property Members

        /// <summary>
        /// 姓名
        /// </summary>
        public virtual string Name { get; set; }

        /// <summary>
        /// 年齡
        /// </summary>
        public virtual int Age { get; set; }

        /// <summary>
        /// 創建人
        /// </summary>
        public virtual string Creator { get; set; }

        /// <summary>
        /// 創建時間
        /// </summary>
        public virtual DateTime CreateTime { get; set; }

        #endregion
    }

其中 Entity<string> 是我們根據需要定義一個基類實體對象,主要就是定義一個Id的屬性來處理,畢竟對於一般表對象的處理,SqlSugar需要Id的主鍵定義(非中間表處理)。

    [Serializable]
    public abstract class Entity<TPrimaryKey> : IEntity<TPrimaryKey>
    {
        /// <summary>
        /// 實體類唯一主鍵
        /// </summary>
        [SqlSugar.SugarColumn(IsPrimaryKey = true, ColumnDescription = "主鍵")]
        public virtual TPrimaryKey Id { get; set; }
    }

而IEntity<T>定義了一個介面

    public interface IEntity<TPrimaryKey>
    {
        /// <summary>
        /// 實體類唯一主鍵
        /// </summary>
        TPrimaryKey Id { get; set; }
    }

以上就是實體類的處理,我們一般為了查詢信息,往往通過一些條件傳入進行處理,那麼我們就需要定義一個通用的分頁查詢對象,供我們精準進行條件的處理。

生成一個以***PageDto的對象類,如下所示。

    /// <summary>
    /// 用於根據條件分頁查詢,DTO對象
    /// </summary>
    public class CustomerPagedDto : PagedAndSortedInputDto, IPagedAndSortedResultRequest
    {
        /// <summary>
        /// 預設構造函數
        /// </summary>
        public CustomerPagedDto() : base() { }

        /// <summary>
        /// 參數化構造函數
        /// </summary>
        /// <param name="skipCount">跳過的數量</param>
        /// <param name="resultCount">最大結果集數量</param>
        public CustomerPagedDto(int skipCount, int resultCount) : base(skipCount, resultCount)
        {
        }

        /// <summary>
        /// 使用分頁信息進行初始化SkipCount 和 MaxResultCount
        /// </summary>
        /// <param name="pagerInfo">分頁信息</param>
        public CustomerPagedDto(PagerInfo pagerInfo) : base(pagerInfo)
        {
        }

        #region Property Members

        /// <summary>
        /// 不包含的對象的ID,用於在查詢的時候排除對應記錄
        /// </summary>
        public virtual string ExcludeId { get; set; }

        /// <summary>
        /// 姓名
        /// </summary>
        public virtual string Name { get; set; }

        /// <summary>
        /// 年齡-開始
        /// </summary>
        public virtual int? AgeStart { get; set; }
        /// <summary>
        /// 年齡-結束
        /// </summary>
        public virtual int? AgeEnd { get; set; }

        /// <summary>
        /// 創建時間-開始
        /// </summary>
        public DateTime? CreateTimeStart { get; set; }
        /// <summary>
        /// 創建時間-結束
        /// </summary>
        public DateTime? CreateTimeEnd { get; set; }

        #endregion
    }

其中PagedAndSortedInputDto, IPagedAndSortedResultRequest都是參考來自於ABP/ABP VNext的處理方式,這樣我們可以便於數據訪問基類的查詢處理操作。

接著我們定義一個基類MyCrudService,並傳遞如相關的泛型約束,如下所示

    /// <summary>
    /// 基於SqlSugar的資料庫訪問操作的基類對象
    /// </summary>
    /// <typeparam name="TEntity">定義映射的實體類</typeparam>
    /// <typeparam name="TKey">主鍵的類型,如int,string等</typeparam>
    /// <typeparam name="TGetListInput">或者分頁信息的條件對象</typeparam>
    public abstract class MyCrudService<TEntity, TKey, TGetListInput> : 
        IMyCrudService<TEntity, TKey, TGetListInput>
        where TEntity : class, IEntity<TKey>, new()
        where TGetListInput : IPagedAndSortedResultRequest

我們先忽略基類介面的相關實現細節,我們看看對於這個MyCrudService和 IMyCrudService 我們應該如何使用的。

首先我們定義一個應用層的介面ICustomerService如下所示。

    /// <summary>
    /// 客戶信息服務介面
    /// </summary>
    public interface ICustomerService : IMyCrudService<CustomerInfo, string, CustomerPagedDto>, ITransientDependency
    {

    }

然後實現在CustomerService中實現它的介面。

    /// <summary>
    /// 應用層服務介面實現
    /// </summary>
    public class CustomerService : MyCrudService<CustomerInfo, string, CustomerPagedDto>, ICustomerService

這樣我們對於特定Customer的介面在ICustomer中定義,標準介面直接調用基類即可。

基類MyCrudService提供重要的兩個介面,讓子類進行重寫,以便於進行準確的條件處理和排序處理,如下代碼所示。

    /// <summary>
    /// 基於SqlSugar的資料庫訪問操作的基類對象
    /// </summary>
    /// <typeparam name="TEntity">定義映射的實體類</typeparam>
    /// <typeparam name="TKey">主鍵的類型,如int,string等</typeparam>
    /// <typeparam name="TGetListInput">或者分頁信息的條件對象</typeparam>
    public abstract class MyCrudService<TEntity, TKey, TGetListInput> : 
        IMyCrudService<TEntity, TKey, TGetListInput>
        where TEntity : class, IEntity<TKey>, new()
        where TGetListInput : IPagedAndSortedResultRequest
    {
        /// <summary>
        /// 留給子類實現過濾條件的處理
        /// </summary>
        /// <returns></returns>
        protected virtual ISugarQueryable<TEntity> CreateFilteredQueryAsync(TGetListInput input)
        {
            return EntityDb.AsQueryable();
        }
        /// <summary>
        /// 預設排序,通過ID進行排序
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        protected virtual ISugarQueryable<TEntity> ApplyDefaultSorting(ISugarQueryable<TEntity> query)
        {
            if (typeof(TEntity).IsAssignableTo<IEntity<TKey>>())
            {
                return query.OrderBy(e => e.Id);
            }
            else
            {
                return query.OrderBy("Id");
            }
        }        
    }

對於Customer特定的業務對象來說,我們需要實現具體的條件查詢細節和排序條件,畢竟我們父類沒有約束確定實體類有哪些屬性的情況下,這些就交給子類做最合適了。

    /// <summary>
    /// 應用層服務介面實現
    /// </summary>
    public class CustomerService : MyCrudService<CustomerInfo, string, CustomerPagedDto>, ICustomerService
    {
        /// <summary>
        /// 自定義條件處理
        /// </summary>
        /// <param name="input">查詢條件Dto</param>
        /// <returns></returns>
        protected override ISugarQueryable<CustomerInfo> CreateFilteredQueryAsync(CustomerPagedDto input)
        {
            var query = base.CreateFilteredQueryAsync(input);

            query = query
                .WhereIF(!input.ExcludeId.IsNullOrWhiteSpace(), t => t.Id != input.ExcludeId) //不包含排除ID
                .WhereIF(!input.Name.IsNullOrWhiteSpace(), t => t.Name.Contains(input.Name)) //如需要精確匹配則用Equals
                                                                                             //年齡區間查詢
                .WhereIF(input.AgeStart.HasValue, s => s.Age >= input.AgeStart.Value)
                .WhereIF(input.AgeEnd.HasValue, s => s.Age <= input.AgeEnd.Value)

                //創建日期區間查詢
                .WhereIF(input.CreateTimeStart.HasValue, s => s.CreateTime >= input.CreateTimeStart.Value)
                .WhereIF(input.CreateTimeEnd.HasValue, s => s.CreateTime <= input.CreateTimeEnd.Value)
                ;

            return query;
        }

        /// <summary>
        /// 自定義排序處理
        /// </summary>
        /// <param name="query">可查詢LINQ</param>
        /// <returns></returns>
        protected override ISugarQueryable<CustomerInfo> ApplyDefaultSorting(ISugarQueryable<CustomerInfo> query)
        {
            return query.OrderBy(t => t.CreateTime, OrderByType.Desc);

            //先按第一個欄位排序,然後再按第二欄位排序
            //return base.ApplySorting(query, input).OrderBy(s=>s.Customer_ID).OrderBy(s => s.Seq);
        }
    }

通過 CreateFilteredQueryAsync 的精確條件處理,我們就可以明確實體類的查詢條件處理,因此對於CustomerPagedDto來說,就是可以有客戶端傳入,服務後端的基類進行處理了。

如基類的分頁條件查詢函數GetListAsync就是根據這個來處理的,它的實現代碼如下所示。

        /// <summary>
        /// 根據條件獲取列表
        /// </summary>
        /// <param name="input">分頁查詢條件</param>
        /// <returns></returns>
        public virtual async Task<PagedResultDto<TEntity>> GetListAsync(TGetListInput input)
        {
            var query = CreateFilteredQueryAsync(input);
            var totalCount = await query.CountAsync();

            query = ApplySorting(query, input);
            query = ApplyPaging(query, input);

            var list = await query.ToListAsync();

            return new PagedResultDto<TEntity>(
               totalCount,
               list
           );
        }

而其中 ApplySorting 就是根據條件決定是否選擇子類實現的預設排序進行處理的。

        /// <summary>
        /// 記錄排序處理
        /// </summary>
        /// <returns></returns>
        protected virtual ISugarQueryable<TEntity> ApplySorting(ISugarQueryable<TEntity> query, TGetListInput input)
        {
            //Try to sort query if available
            if (input is ISortedResultRequest sortInput)
            {
                if (!sortInput.Sorting.IsNullOrWhiteSpace())
                {
                    return query.OrderBy(sortInput.Sorting);
                }
            }

            //IQueryable.Task requires sorting, so we should sort if Take will be used.
            if (input is ILimitedResultRequest)
            {
                return ApplyDefaultSorting(query);
            }

            //No sorting
            return query;
        }

對於獲取單一對象,我們一般提供一個ID主鍵獲取即可。

        /// <summary>
        /// 根據ID獲取單一對象
        /// </summary>
        /// <param name="id">主鍵ID</param>
        /// <returns></returns>
        public virtual async Task<TEntity> GetAsync(TKey id)
        {
            return await EntityDb.GetByIdAsync(id);
        }

也可以根據用戶的Express條件進行處理,在基類我們定義很多這樣的Express條件處理,便於子類進行條件處理的調用。如對於刪除,可以指定ID,也可以指定條件刪除。

        /// <summary>
        /// 刪除指定ID的對象
        /// </summary>
        /// <param name="id">記錄ID</param>
        /// <returns></returns>
        public virtual async Task<bool> DeleteAsync(TKey id)
        {
            return await EntityDb.DeleteByIdAsync(id);
        }
/// <summary>
        /// 根據指定條件,刪除集合
        /// </summary>
        /// <param name="input">表達式條件</param>
        /// <returns></returns>
        public virtual async Task<bool> DeleteAsync(Expression<Func<TEntity, bool>> input)
        {
            var result = await EntityDb.DeleteAsync(input);
            return result;
        }

如判斷是否存在也是一樣處理

        /// <summary>
        /// 判斷是否存在指定條件的記錄
        /// </summary>
        /// <param name="id">ID 主鍵</param>
        /// <returns></returns>
        public virtual async Task<bool> IsExistAsync(TKey id)
        {
            var info = await EntityDb.GetByIdAsync(id);
            var result = (info != null);
            return result;
        }

        /// <summary>
        /// 判斷是否存在指定條件的記錄
        /// </summary>
        /// <param name="input">表達式條件</param>
        /// <returns></returns>
        public virtual async Task<bool> IsExistAsync(Expression<Func<TEntity, bool>> input)
        {
            var result = await EntityDb.IsAnyAsync(input);
            return result;
        }

關於Web API的處理,我在隨筆《基於SqlSugar的資料庫訪問處理的封裝,在.net6框架的Web API上開發應用》中也有介紹,主要就是先弄好.net6的開發環境,然後在進行相關的項目開發即可。

根據項目的需要,我們定義了一些控制器的基類,用於實現不同的功能。

 

 其中ControllerBase是.net core Web API中的標準控制器基類,我們由此派生一個LoginController用於登錄授權,而BaseApiController則處理常規介面用戶身份信息,而BusinessController則是對標準的增刪改查等基礎介面進行的封裝,我們實際開發的時候,只需要開發編寫類似CustomerController基類即可。

BaseApiController沒有什麼好介紹的,就是封裝一下獲取用戶的身份信息。

可以通過下麵代碼獲取介面用戶的Id

        /// <summary>
        /// 當前用戶身份ID
        /// </summary>
        protected virtual string? CurrentUserId => HttpContext.User.FindFirst(JwtClaimTypes.Id)?.Value;

而BusinessController控制器則是繼承這個BaseApiController即可。通過泛型約束傳入相關的對象信息。

    /// <summary>
    /// 本控制器基類專門為訪問數據業務對象而設的基類
    /// </summary>
    /// <typeparam name="TEntity">定義映射的實體類</typeparam>
    /// <typeparam name="TKey">主鍵的類型,如int,string等</typeparam>
    /// <typeparam name="TGetListInput">或者分頁信息的條件對象</typeparam>
    [Route("[controller]")]
    [Authorize] //需要授權登錄訪問
    public class BusinessController<TEntity, TKey, TGetListInput> : BaseApiController
        where TEntity : class, IEntity<TKey>, new()
        where TGetListInput : IPagedAndSortedResultRequest
    {
        /// <summary>
        /// 通用基礎操作介面
        /// </summary>
        protected IMyCrudService<TEntity, TKey, TGetListInput> _service { get; set; }

        /// <summary>
        /// 構造函數,初始化基礎介面
        /// </summary>
        /// <param name="service">通用基礎操作介面</param>
        public BusinessController(IMyCrudService<TEntity, TKey, TGetListInput> service)
        {
            this._service = service;
        }

....

這個基類接收一個符合基類介面定義的對象作為基類增刪刪改查等處理方法的介面對象。在具體的CustomerController中的定義處理如下所示。

    /// <summary>
    /// 客戶信息的控制器對象
    /// </summary>
    public class CustomerController : BusinessController<CustomerInfo, string, CustomerPagedDto>
    {
        private ICustomerService _customerService;

        /// <summary>
        /// 構造函數,並註入基礎介面對象
        /// </summary>
        /// <param name="customerService"></param>
        public CustomerController(ICustomerService customerService) :base(customerService)
        {
            this._customerService = customerService;
        }
    }

這樣就可以實現基礎的相關操作了。如果需要特殊的介面實現,那麼定義方法實現即可。

類似字典項目中的控制器處理代碼如下所示。定義好HTTP方法,路由信息等即可。

        /// <summary>
        /// 根據字典類型ID獲取所有該類型的字典列表集合(Key為名稱,Value為值)
        /// </summary>
        /// <param name="dictTypeId">字典類型ID</param>
        /// <returns></returns>
        [HttpGet]
        [Route("by-typeid/{dictTypeId}")]
        public async Task<Dictionary<string, string>> GetDictByTypeID(string dictTypeId)
        {
            return await _dictDataService.GetDictByTypeID(dictTypeId);
        }

        /// <summary>
        /// 根據字典類型名稱獲取所有該類型的字典列表集合(Key為名稱,Value為值)
        /// </summary>
        /// <param name="dictTypeName">字典類型名稱</param>
        /// <returns></returns>
        [HttpGet]
        [Route("by-typename/{dictTypeName}")]
        public async Task<Dictionary<string, string>> GetDictByDictType(string dictTypeName)
        {
            return await _dictDataService.GetDictByDictType(dictTypeName);
        }

 

系列文章:

基於SqlSugar的開發框架的循序漸進介紹(1)--框架基礎類的設計和使用

基於SqlSugar的開發框架循序漸進介紹(2)-- 基於中間表的查詢處理

基於SqlSugar的開發框架循序漸進介紹(3)-- 實現代碼生成工具Database2Sharp的整合開發

 

主要研究技術:代碼生成工具、會員管理系統、客戶關係管理軟體、病人資料管理軟體、Visio二次開發、酒店管理系統、倉庫管理系統等共用軟體開發
專註於Winform開發框架/混合式開發框架Web開發框架Bootstrap開發框架微信門戶開發框架的研究及應用
  轉載請註明出處:
撰寫人:伍華聰  http://www.iqidi.com 
    

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

-Advertisement-
Play Games
更多相關文章
  • 作者:等不到的口琴 鏈接:https://www.cnblogs.com/Courage129/p/14446586.html 本文準備圍繞七個點來講網關,分別是網關的基本概念、網關設計思路、網關設計重點、流量網關、業務網關、常見網關對比,對基礎概念熟悉的朋友可以根據目錄查看自己感興趣的部分。 什麼 ...
  • 期中考試題目總結 (1)總結:期中考試主要考察的是點線面類的設計,之前沒有接觸過類,或者說對類沒有什麼很清晰的概念和認知。現在才發現“類”是一個非常強大的工具,可以大大方便我們平時解決問題的過程。期中考試這幾道題目難度適中,很適合我們平時拿來練手,不過也需要抓住各種細節,以防出現一些不該出現的錯誤。 ...
  • 上周遇到個靈異事件,實驗室有兩套環境來搭建redis集群和哨兵,分別是: 第一套環境IP:67(master) 65(salve) 66(salve)第二套環境IP:115(master) 116(salve) 117(salve) 第一天把哨兵搭建好後,兩套環境的主從關係都是一主兩從,但是到了第二 ...
  • 1、線程cpu占用過高 1. top命令發現java程式長時間占用過高的cpu 2. ps H pid,tid,%cpu | grep 進程號PID 3. 使用java工具jstack jstack PID 發現具體線程情況 4. 將tid線程轉換為十六進位去查找具體的線程 5. echo 'oba ...
  • 1.Minio及背景 Minio是一個開源的分散式文件存儲系統,它基於 Golang 編寫,雖然輕量,卻擁有著不錯的高性能,可以將圖片、視頻、音樂、pdf這些文件存儲到多個主機,可以存儲到多個Linux,或者多個Windows,或者多個Mac,Minio中存儲最大文件可以達到5TB。任何類型的文件都 ...
  • 我喜歡在一個項目開發模式成熟的時候,使用代碼生成工具Database2Sharp來配套相關的代碼生成,對於我介紹的基於SqlSugar的開發框架,從整體架構確定下來後,我就著手為它們量身定做相關的代碼開發,這樣可以在後續整合項目功能的時候,利用代碼生成工具快速的生成所需要模塊的骨架代碼,然後在這個基... ...
  • 引言 在使用 Visual Studio 進行 Docker 運行調試的時候會出現無法調試的問題。 出現類似一下癥狀: Info: Using vsdbg version '17.2.10512.2' Info: Using Runtime ID 'linux-x64' Info: C:\Users ...
  • 在前面介紹的SqlSugar的相關查詢處理操作中,我們主要以單表的方式生成相關的實體類,併在查詢的時候,對單表的欄位進行條件的對比處理,從而返回對應的數據記錄。本篇隨筆介紹在一些外鍵或者中間表的處理中,如何遍歷查詢並獲得所需的記錄操作。 ...
一周排行
    -Advertisement-
    Play Games
  • GoF之工廠模式 @目錄GoF之工廠模式每博一文案1. 簡單說明“23種設計模式”1.2 介紹工廠模式的三種形態1.3 簡單工廠模式(靜態工廠模式)1.3.1 簡單工廠模式的優缺點:1.4 工廠方法模式1.4.1 工廠方法模式的優缺點:1.5 抽象工廠模式1.6 抽象工廠模式的優缺點:2. 總結:3 ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 本章將和大家分享ES的數據同步方案和ES集群相關知識。廢話不多說,下麵我們直接進入主題。 一、ES數據同步 1、數據同步問題 Elasticsearch中的酒店數據來自於mysql資料庫,因此mysql數據發生改變時,Elasticsearch也必須跟著改變,這個就是Elasticsearch與my ...
  • 引言 在我們之前的文章中介紹過使用Bogus生成模擬測試數據,今天來講解一下功能更加強大自動生成測試數據的工具的庫"AutoFixture"。 什麼是AutoFixture? AutoFixture 是一個針對 .NET 的開源庫,旨在最大程度地減少單元測試中的“安排(Arrange)”階段,以提高 ...
  • 經過前面幾個部分學習,相信學過的同學已經能夠掌握 .NET Emit 這種中間語言,並能使得它來編寫一些應用,以提高程式的性能。隨著 IL 指令篇的結束,本系列也已經接近尾聲,在這接近結束的最後,會提供幾個可供直接使用的示例,以供大伙分析或使用在項目中。 ...
  • 當從不同來源導入Excel數據時,可能存在重覆的記錄。為了確保數據的準確性,通常需要刪除這些重覆的行。手動查找並刪除可能會非常耗費時間,而通過編程腳本則可以實現在短時間內處理大量數據。本文將提供一個使用C# 快速查找並刪除Excel重覆項的免費解決方案。 以下是實現步驟: 1. 首先安裝免費.NET ...
  • C++ 異常處理 C++ 異常處理機制允許程式在運行時處理錯誤或意外情況。它提供了捕獲和處理錯誤的一種結構化方式,使程式更加健壯和可靠。 異常處理的基本概念: 異常: 程式在運行時發生的錯誤或意外情況。 拋出異常: 使用 throw 關鍵字將異常傳遞給調用堆棧。 捕獲異常: 使用 try-catch ...
  • 優秀且經驗豐富的Java開發人員的特征之一是對API的廣泛瞭解,包括JDK和第三方庫。 我花了很多時間來學習API,尤其是在閱讀了Effective Java 3rd Edition之後 ,Joshua Bloch建議在Java 3rd Edition中使用現有的API進行開發,而不是為常見的東西編 ...
  • 框架 · 使用laravel框架,原因:tp的框架路由和orm沒有laravel好用 · 使用強制路由,方便介面多時,分多版本,分文件夾等操作 介面 · 介面開發註意欄位類型,欄位是int,查詢成功失敗都要返回int(對接java等強類型語言方便) · 查詢介面用GET、其他用POST 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...