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

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

在前面介紹的SqlSugar的相關查詢處理操作中,我們主要以單表的方式生成相關的實體類,併在查詢的時候,對單表的欄位進行條件的對比處理,從而返回對應的數據記錄。本篇隨筆介紹在一些外鍵或者中間表的處理中,如何遍歷查詢並獲得所需的記錄操作。 ...


在前面介紹的SqlSugar的相關查詢處理操作中,我們主要以單表的方式生成相關的實體類,併在查詢的時候,對單表的欄位進行條件的對比處理,從而返回對應的數據記錄。本篇隨筆介紹在一些外鍵或者中間表的處理中,如何遍歷查詢並獲得所需的記錄操作。

1、回顧單表的操作查詢

我在《基於SqlSugar的開發框架的循序漸進介紹(1)--框架基礎類的設計和使用》中介紹過的Customer表信息,就是一個單表的處理。

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

生成對應的實體對象CustomerInfo外,同時生成 CustomerPagedDto  的分頁查詢條件對象。

在繼承基類後

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

並重寫 CreateFilteredQueryAsync 函數,從而實現了條件的精確查詢處理。

    /// <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;
        }

在表的對應實體信息沒有其他表關聯的時候,我們直接通過SqlSugar的基礎介面返回對象列表即可。

通過 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
           );
        }

也就是說只要繼承了 CustomerService ,我們預設調用基類的 GetListAsync 就可以返回對應的列表記錄了。

如在Web API的控制器中調用獲取記錄返回,調用處理的代碼如下所示。

        /// <summary>
        /// 獲取所有記錄
        /// </summary>
        [HttpGet]
        [Route("all")]
        [HttpGet]public virtual async Task<ListResultDto<TEntity>> GetAllAsync()
        {
            //檢查用戶是否有許可權,否則拋出MyDenyAccessException異常
            base.CheckAuthorized(AuthorizeKey.ListKey);

            return await _service.GetAllAsync();
        }

而對於Winform的調用,我們這裡首先利用代碼生成工具生成對應的界面和代碼

  查看其調用的界面代碼

 而其中GetData中的函數部分內容如下所示。

        /// <summary>
        /// 獲取數據
        /// </summary>
        /// <returns></returns>
        private async Task<IPagedResult<CustomerInfo>> GetData()
        {
            CustomerPagedDto pagerDto = null;
            if (advanceCondition != null)
            {
                //如果有高級查詢,那麼根據輸入信息構建查詢條件
                pagerDto = new CustomerPagedDto(this.winGridViewPager1.PagerInfo);
                pagerDto = dlg.GetPagedResult(pagerDto);
            }
            else
            {
                //構建分頁的條件和查詢條件
                pagerDto = new CustomerPagedDto(this.winGridViewPager1.PagerInfo)
                {
                    //添加所需條件
                    Name = this.txtName.Text.Trim(),
                };

                //日期和數值範圍定義
                //年齡,需在CustomerPagedDto中添加 int? 類型欄位AgeStart和AgeEnd
                var Age = new ValueRange<int?>(this.txtAge1.Text, this.txtAge2.Text); //數值類型
                pagerDto.AgeStart = Age.Start;
                pagerDto.AgeEnd = Age.End;

                //創建時間,需在CustomerPagedDto中添加 DateTime? 類型欄位CreationTimeStart和CreationTimeEnd
                var CreationTime = new TimeRange(this.txtCreationTime1.Text, this.txtCreationTime2.Text); //日期類型
                pagerDto.CreateTimeStart = CreationTime.Start;
                pagerDto.CreateTimeEnd = CreationTime.End;
            }

            var result = await BLLFactory<CustomerService>.Instance.GetListAsync(pagerDto);
            return result;
        }

列表界面效果如下所示。

  

2、基於中間表的查詢處理

前面的查詢處理,主要就是針對沒有任何關係的表實體對象的返回處理,但往往我們開發的時候,會涉及到很多相關的表,單獨的表相對來說還是比較少,因此對錶的關係遍歷處理和中間表的關係轉換,就需要在數據操作的時候考慮的了。

例如對於字典大類和字典項目的關係,如下所示。

 以及在許可權管理系統模塊中,用戶、角色、機構、許可權等存在著很多中間表的關係,如下所示。

 

如對於字典表關係處理,我們採用Queryable<DictDataInfo, DictTypeInfo>的查詢處理方式,可以聯合兩個表對象實體進行聯合查詢,如下代碼所示。

        /// <summary>
        /// 根據字典類型名稱獲取所有該類型的字典列表集合(Key為名稱,Value為值)
        /// </summary>
        /// <param name="dictTypeName">字典類型名稱</param>
        /// <returns></returns>
        public async Task<Dictionary<string, string>> GetDictByDictType(string dictTypeName)
        {
            var query = this.Client.Queryable<DictDataInfo, DictTypeInfo>(
                (d, t) => d.DictType_ID == t.Id && t.Name == dictTypeName)
                .Select(d => d); //聯合條件獲取對象

            query = query.OrderBy(d => d.DictType_ID).OrderBy(d => d.Seq);//排序
            var list = await query.ToListAsync();//獲取列表

            var dict = new Dictionary<string, string>();
            foreach (var info in list)
            {
                if (!dict.ContainsKey(info.Name))
                {
                    dict.Add(info.Name, info.Value);
                }
            }
            return dict;
        }

其中的Client對象是DbContext對象實例的Client屬性,如下圖所示。

 

這個對象是在DbContext對象中構建的,如下所示。

            this.Client = new SqlSugarScope(new ConnectionConfig()
            {
                DbType = this.DbType,
                ConnectionString = this.ConnectionString,
                InitKeyType = InitKeyType.Attribute,
                IsAutoCloseConnection = true, //是否自動關閉連接
                AopEvents = new AopEvents
                {
                    OnLogExecuting = (sql, p) =>
                    {
                        //Log.Information(sql);
                        //Log.Information(string.Join(",", p?.Select(it => it.ParameterName + ":" + it.Value)));
                    }
                }
            });

我們查看Queryable,可以看到這個SqlSugar基類函數 Queryable 提供了很多重載函數,也就是它們可以提供更多的表對象進行聯合查詢的,如下所示。

 

 前面介紹的是外鍵的一對多的關係查詢,通過兩個對象之間進行的關係連接,從而實現另一個對象屬性的對比查詢操作的。

對於中間表的處理,也是類似的情況,我們通過對比中間表的屬性,從而實現條件的過濾處理。如下是對於角色中相關關係的中間表查詢。

        /// <summary>
        /// 根據用戶ID獲取對應的角色列表
        /// </summary>
        /// <param name="userID">用戶ID</param>
        /// <returns></returns>
        private async Task<List<RoleInfo>> GetByUser(int userID)
        {
            var query = this.Client.Queryable<RoleInfo, User_RoleInfo>(
            (t, m) => t.Id == m.Role_ID && m.User_ID == userID)
            .Select(t => t); //聯合條件獲取對象

            query = query.OrderBy(t => t.CreateTime);//排序
            var list = await query.ToListAsync();//獲取列表
            return list;
        }

        /// <summary>
        /// 根據機構獲取對應的角色列表(判斷機構角色中間表)
        /// </summary>
        /// <param name="ouID">機構的ID</param>
        /// <returns></returns>
        public async Task<List<RoleInfo>> GetRolesByOu(int ouID)
        {
            var query = this.Client.Queryable<RoleInfo, OU_RoleInfo>(
            (t, m) => t.Id == m.Role_ID && m.Ou_ID == ouID)
            .Select(t => t); //聯合條件獲取對象

            query = query.OrderBy(t => t.CreateTime);//排序
            var list = await query.ToListAsync();//獲取列表
            return list;
        }

通過聯合查詢中間表對象信息,可以對它的欄位屬性進行條件聯合,從而獲得所需的記錄。

這裡User_RoleInfo和Ou_RoleInfo表也是根據中間表的屬性生成的,不過它們在業務層並沒有任何關聯操作,也不需要生成對應的Service層,因此只需要生成相關的Model類實體即可。

    /// <summary>
    /// 用戶角色關聯
    /// </summary>
    [SugarTable("T_ACL_User_Role")]
    public class User_RoleInfo
    {         
        /// <summary>
        /// 用戶ID
        /// </summary>
        [Required]
        public virtual int User_ID { get; set; }

        /// <summary>
        /// 角色ID
        /// </summary>
        [Required]
        public virtual int Role_ID { get; set; }

    }
    /// <summary>
    /// 機構角色關聯
    /// </summary>
    [SugarTable("T_ACL_OU_Role")]
    public class OU_RoleInfo 
    {         
        /// <summary>
        /// 機構ID
        /// </summary>
        [Required]
        public virtual int Ou_ID { get; set; }

        /// <summary>
        /// 角色ID
        /// </summary>
        [Required]
        public virtual int Role_ID { get; set; }
    }

可以看到這兩個實體不同於其他實體,它們沒有基類繼承關係,而一般標準的實體是有的。

    /// <summary>
    /// 角色信息
    /// </summary>
    [SugarTable("T_ACL_Role")]
    public class RoleInfo : Entity<int> {  }


    /// <summary>
    /// 功能菜單
    /// </summary>
    [SugarTable("T_ACL_Menu")]
    public class MenuInfo : Entity<string> { }

所以我們就不需要構建它們的Service層來處理數據,它的存在合理性只是在於能夠和其他實體對象進行表的聯合查詢處理而且。

最後貼上一個整合SqlSugar處理而完成的系統基礎框架的Winform端界面,其中包括用戶、組織機構、角色管理、許可權管理、菜單管理、日誌、字典、客戶信息等業務表的處理。

以證所言非虛。

 

系列文章:

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

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

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

 

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

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

-Advertisement-
Play Games
更多相關文章
  • 驗證碼的功能是防止非法用戶惡意去訪問登錄介面而設置的一個功能,今天我們就來看看在前後端分離的項目中,SpringBoot是如何提供服務的。 SpringBoot版本 本文基於的Spring Boot的版本是2.6.7 。 引入依賴 captcha一款超簡單的驗證碼生成,還挺好玩的.還有中文驗證碼,動 ...
  • 作者:等不到的口琴 鏈接: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 ...
一周排行
    -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 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...