ABP開發框架前後端開發系列---(13)高級查詢功能及界面的處理

来源:https://www.cnblogs.com/wuhuacong/archive/2019/07/03/11121503.html
-Advertisement-
Play Games

在一般的檢索界面中,基於界面易用和美觀方便的考慮,我們往往只提供一些常用的條件查詢進行列表數據的查詢,但是有時候一些業務表欄位很多,一些不常見的條件可能在某些場景下也需要用到。因此我們在通用的查詢條件之外,一般可以考慮增加 一個高級查詢的模塊來管理這些不常見條件的查詢處理。本篇隨筆基於這個需求,綜合... ...


在一般的檢索界面中,基於界面易用和美觀方便的考慮,我們往往只提供一些常用的條件查詢進行列表數據的查詢,但是有時候一些業務表欄位很多,一些不常見的條件可能在某些場景下也需要用到。因此我們在通用的查詢條件之外,一般可以考慮增加 一個高級查詢的模塊來管理這些不常見條件的查詢處理。本篇隨筆基於這個需求,綜合ABP框架的特點,整合了高級查詢模塊功能的處理。

1、高級查詢模塊的回顧

我們知道,在界面佈局中,一般常見的查詢條件不能太多,否則會顯得臃腫而且占用太多空間,非常不美觀,因此常見的查詢都是提供寥寥幾個的輸出條件進行列表記錄的查詢的。

又或者一些更多內容的界面,我們也是僅僅提供多幾個條件,其他的想辦法通過高級查詢界面進行查詢管理。

在早期博客裡面《Winform開發框架之通用高級查詢模塊》,我曾經介紹過一款通用的高級查詢界面處理,用在Winform框架裡面,可以對數據表更多的欄位進行統一的查詢處理。

對於內容較多的查詢,我們可以在主界面增加一個高級查詢按鈕入口,如上圖所示,單擊後,顯示一個所有欄位的列表,如下界面。

一般來說,查詢條件分為文本輸入,如姓名,郵件,名稱等這些。

日期類型條件輸入界面:

數字類型條件輸入界面:

 輸入以上幾種條件後,高級查詢界面裡面會顯示友好的條件內容,確保用戶能夠看懂輸入的條件,如下所示是輸入幾個不同類型的條件的顯示內容。

以上是高級查詢模塊的思路,整體界面和處理邏輯雖然可以採用,但是在ABP框架模式下,以前的處理方式有所不同了,下麵詳細介紹一下如何在ABP框架模塊下整合這個高級查詢模塊的內容。

 

2、ABP框架模塊下的高級查詢處理

我們先來瞭解一下最終在ABP框架下整合的高級查詢模塊界面如下所示。

可以設置一些模糊查詢條件,以及一些區間的查詢值,如下所示。

這個模塊是以ABP框架的Web API獲取數據,並通過Winform界面進行調用,從而形成了一個ABP+Winform的框架體系。

前面ABP框架系列介紹過,我們一般使用GetAll和分頁條件DTO進行數據的檢索,如下是產品分頁DTO的定義

    /// <summary>
    /// 用於根據條件分頁查詢,DTO對象
    /// </summary>
    public class ProductPagedDto : PagedAndSortedInputDto

而PagedAndSortedInputDto也是自定義的類,它主要用來承載一些分頁和排序的信息,如下所示

    /// <summary>
    /// 帶有排序對象的分頁基類
    /// </summary>
    public class PagedAndSortedInputDto : PagedInputDto, ISortedResultRequest
    {
        /// <summary>
        /// 排序信息
        /// </summary>
        public string Sorting { get; set; }

其中的PagedInputDto也是自定義類,主要承載分頁信息。

    /// <summary>
    /// 分頁對象
    /// </summary>
    public class PagedInputDto : IPagedResultRequest
    {
        [Range(1, int.MaxValue)]
        public int MaxResultCount { get; set; }

        [Range(0, int.MaxValue)]
        public int SkipCount { get; set; }

        public PagedInputDto()
        {
            MaxResultCount = int.MaxValue;
        }
    }

這樣的構建,我們可以傳遞分頁和排序信息,因此在GetAll函數裡面,就可以根據這些條件進行數據查詢了。

而我們通過重寫過濾條件和排序處理,就可以實現數據的分頁查詢了。對於產品信息的過濾處理和排序處理,我們重寫函數如下所示。

        /// <summary>
        /// 自定義條件處理
        /// </summary>
        /// <param name="input">查詢條件Dto</param>
        /// <returns></returns>
        protected override IQueryable<Product> CreateFilteredQuery(ProductPagedDto input)
        {
            return base.CreateFilteredQuery(input)
                .WhereIf(!input.ExcludeId.IsNullOrWhiteSpace(), t => t.Id != input.ExcludeId) //不包含排除ID

                .WhereIf(!input.ProductNo.IsNullOrWhiteSpace(), t => t.ProductNo.Contains(input.ProductNo)) //如需要精確匹配則用Equals
                .WhereIf(!input.BarCode.IsNullOrWhiteSpace(), t => t.BarCode.Contains(input.BarCode)) //如需要精確匹配則用Equals
                .WhereIf(!input.MaterialCode.IsNullOrWhiteSpace(), t => t.MaterialCode.Contains(input.MaterialCode)) //如需要精確匹配則用Equals
                .WhereIf(!input.ProductType.IsNullOrWhiteSpace(), t => t.ProductType.Contains(input.ProductType)) //如需要精確匹配則用Equals
                .WhereIf(!input.ProductName.IsNullOrWhiteSpace(), t => t.ProductName.Contains(input.ProductName)) //如需要精確匹配則用Equals
                .WhereIf(!input.Unit.IsNullOrWhiteSpace(), t => t.Unit.Contains(input.Unit)) //如需要精確匹配則用Equals
                .WhereIf(!input.Note.IsNullOrWhiteSpace(), t => t.Note.Contains(input.Note)) //如需要精確匹配則用Equals
                .WhereIf(!input.Description.IsNullOrWhiteSpace(), t => t.Description.Contains(input.Description)) //如需要精確匹配則用Equals
                 
                 //狀態
                .WhereIf(input.Status.HasValue, t => t.Status==input.Status)
                                                                                              
                 //成本價區間查詢
                .WhereIf(input.PriceStart.HasValue, s => s.Price >= input.PriceStart.Value)
                .WhereIf(input.PriceEnd.HasValue, s => s.Price <= input.PriceEnd.Value)

                //銷售價區間查詢
                .WhereIf(input.SalePriceStart.HasValue, s => s.SalePrice >= input.SalePriceStart.Value)
                .WhereIf(input.SalePriceEnd.HasValue, s => s.SalePrice <= input.SalePriceEnd.Value)

                //特價區間查詢
                .WhereIf(input.SpecialPriceStart.HasValue, s => s.SpecialPrice >= input.SpecialPriceStart.Value)
                .WhereIf(input.SpecialPriceEnd.HasValue, s => s.SpecialPrice <= input.SpecialPriceEnd.Value)
                .WhereIf(input.IsUseSpecial.HasValue, t => t.IsUseSpecial == input.IsUseSpecial) //如需要精確匹配則用Equals
                                                                                                  
                //最低折扣區間查詢
                .WhereIf(input.LowestDiscountStart.HasValue, s => s.LowestDiscount >= input.LowestDiscountStart.Value)
                .WhereIf(input.LowestDiscountEnd.HasValue, s => s.LowestDiscount <= input.LowestDiscountEnd.Value)

                //創建日期區間查詢
                .WhereIf(input.CreationTimeStart.HasValue, s => s.CreationTime >= input.CreationTimeStart.Value)
                .WhereIf(input.CreationTimeEnd.HasValue, s => s.CreationTime <= input.CreationTimeEnd.Value);
        }

        /// <summary>
        /// 自定義排序處理
        /// </summary>
        /// <param name="query">可查詢LINQ</param>
        /// <param name="input">查詢條件Dto</param>
        /// <returns></returns>
        protected override IQueryable<Product> ApplySorting(IQueryable<Product> query, ProductPagedDto input)
        {
            //按創建時間倒序排序
            return base.ApplySorting(query, input).OrderByDescending(s => s.CreationTime);//時間降序
        }

雖然我們一般在界面上不會放置所有的條件,但是高級查詢模塊倒是可以把分頁條件DTO裡面的條件全部擺上去的。

高級查詢模塊的條件如下所示。

 我們高級查詢裡面的條件還是以GetAll裡面的對象分頁查詢Dto裡面的屬性,我們需要根據這些條件進行構建,也需要以這些屬性的類型進行一個控制項的選擇。

因此我們需要一個屬性的名稱說明,以及在高級查詢模塊的列表界面中對顯示那些欄位進行控制,如下代碼所示。

        private FrmAdvanceSearch dlg;
        /// <summary>
        /// 高級查詢的操作
        /// </summary>        
        private async void AdvanceSearch()
        {
            if (dlg == null)
            {
                dlg = new FrmAdvanceSearch();
                dlg.SetFieldTypeList<ProductPagedDto>();//通過分頁對象獲取查詢屬性和類型 
                dlg.ColumnNameAlias = await ProductApiCaller.Instance.GetColumnNameAlias();                
                dlg.DisplayColumns = "ProductNo,BarCode,MaterialCode,ProductType,ProductName,Unit,Price,SalePrice,SpecialPrice,IsUseSpecial,LowestDiscount,Note,Description,Status,CreatorUserId,CreationTime";

通過 SetFieldTypeList<ProductPagedDto> 的處理,我們把分頁對象的查詢屬性和類型賦值給了高級查詢模塊,讓它根據類型來創建不同的輸入顯示,如常規的字元串、數值區段、日期區段,下拉列表等等。

對於下拉列表,我們需要綁定它的數據源,如下代碼所示。

 dlg.AddColumnListItem("ProductType", await DictItemUtil.GetDictListItemByDictType("產品類型"));//字典列表
 dlg.AddColumnListItem("Status", await DictItemUtil.GetDictListItemByDictType("產品狀態"));//字典列表

而對於一些常規的固定列表,也可以以類似的方式加入下拉列表

    //固定轉義的列表
    var specialList = new List<CListItem>() { new CListItem("特價", "True"), new CListItem("一般", "False") };
    dlg.AddColumnListItem("IsUseSpecial", specialList);

或者

    dlg.AddColumnListItem("Sex", "男,女");//固定列表

因此整個調用高級查詢模塊的代碼如下所示

    private FrmAdvanceSearch dlg;
    /// <summary>
    /// 高級查詢的操作
    /// </summary>        
    private async void AdvanceSearch()
    {
        if (dlg == null)
        {
            dlg = new FrmAdvanceSearch();
            dlg.SetFieldTypeList<ProductPagedDto>();//通過分頁對象獲取查詢屬性和類型 
            dlg.ColumnNameAlias = await ProductApiCaller.Instance.GetColumnNameAlias();                
            dlg.DisplayColumns = "ProductNo,BarCode,MaterialCode,ProductType,ProductName,Unit,Price,SalePrice,SpecialPrice,IsUseSpecial,LowestDiscount,Note,Description,Status,CreatorUserId,CreationTime";

            #region 下拉列表數據

            dlg.AddColumnListItem("ProductType", await DictItemUtil.GetDictListItemByDictType("產品類型"));//字典列表
            dlg.AddColumnListItem("Status", await DictItemUtil.GetDictListItemByDictType("產品狀態"));//字典列表

            //固定轉義的列表
            var specialList = new List<CListItem>() { new CListItem("特價", "True"), new CListItem("一般", "False") };
            dlg.AddColumnListItem("IsUseSpecial", specialList);

            //dlg.AddColumnListItem("Sex", "男,女");//固定列表
            //dlg.AddColumnListItem("Credit", await ProductApiCaller.Instance.GetFieldList("Credit"));//動態列表

            #endregion

            dlg.ConditionChanged += new FrmAdvanceSearch.ConditionChangedEventHandler(dlg_ConditionChanged);
        }
        dlg.ShowDialog();
    }

在處理獲取數據GetData函數的時候,我們需要根據高級查詢進行一定的切換,以便顯示正確的過濾條件,如下代碼所示是獲取數據的處理。

        /// <summary>
        /// 獲取數據
        /// </summary>
        /// <returns></returns>
        private async Task<IPagedResult<ProductDto>> GetData()
        {
            ProductPagedDto pagerDto = null;
            if (advanceCondition != null)
            {
                pagerDto = new ProductPagedDto(this.winGridViewPager1.PagerInfo);
                pagerDto = dlg.GetPagedResult(pagerDto);               
            }
            else
            {
                //構建分頁的條件和查詢條件
                pagerDto = new ProductPagedDto(this.winGridViewPager1.PagerInfo)
                {
                    //添加所需條件
                    ProductNo = this.txtProductNo.Text.Trim(),
                    BarCode = this.txtBarCode.Text.Trim(),
                    MaterialCode = this.txtMaterialCode.Text.Trim(),
                    ProductType = this.txtProductType.Text.Trim(),
                    ProductName = this.txtProductName.Text.Trim(),
                    Description = this.txtDescription.Text.Trim(),
                };

                //日期和數值範圍定義
                //創建時間,需在ProductPagedDto中添加DateTime?類型欄位CreationTimeStart和CreationTimeEnd
                var CreationTime = new TimeRange(this.txtCreationTime1.Text, this.txtCreationTime2.Text); //日期類型
                pagerDto.CreationTimeStart = CreationTime.Start;
                pagerDto.CreationTimeEnd = CreationTime.End;

            }

            var result = await ProductApiCaller.Instance.GetAll(pagerDto);
            return result;
        }

在高級查詢的處理方式下,我們是傳入一個列表的分頁對象屬性,然後傳入一個分頁DTO對象,就可以構建出我們需要的分頁查詢條件,傳遞給Web API端獲取對應條件的數據了。

    pagerDto = new ProductPagedDto(this.winGridViewPager1.PagerInfo);
    pagerDto = dlg.GetPagedResult(pagerDto);        

而高級查詢模塊,所需要處理的邏輯就是需要根據不同的屬性類型,賦值常規的屬性值或者區段屬性值,從而構建出分頁對應的屬性條件即可。

如果是區段(包括日期或者數值)的,我們分頁查詢條件裡面,會有一個ABCStart,ABCEnd的對象屬性,依照這個規則,獲取到對應的用戶輸入,採用反射方式賦值DTO對象即可。

 


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

-Advertisement-
Play Games
更多相關文章
  • 命令執行位置:工具=〉Nuget包管理器=〉程式包管理器控制台 一、安裝 1.安裝指定版本類庫install-package <程式包名> -version <版本號> 2.安裝到指定的項目install-package <程式包名> -project XXXProjectName -version ...
  • Array類 a) IEumerable介面是由foreach語句用於迭代數組的介面。 b) ICollection介面派生於IEumerable介面,這個介面主要用於確定集合中的元素個數,或用於同步。 c) IList介面派生於ICollection介面,Array類實現IList介面的主要原因是 ...
  • 在 asp.net core 中全局異常處理,有時候可能不能滿足我們的需要,可能就需要自己自定義一個中間件處理了,最近遇到一個問題,有一些異常,不希望記錄錯誤日誌,目前主要是用戶請求取消導致的 `TaskCanceledException` 和 `OperationCanceledException... ...
  • 前段時間我一直在研究PIE SDK與Python的結合,因為在我的開發中,我想獲取一張圖片的統計直方圖,雖然在SDK中有提供關於直方圖的類介面(如IStatsHistogram 介面、HistogramStatDialog 類),但其中有些方法得到的結果數據是有些小問題的(已經向技術人員反應),所以 ...
  • 先 NuGet兩個程式集 1:MongoDB.Driver、 2:MongoDB.Bson namespace ConsoleApp1{ /// <summary> /// MongoDb幫助類 /// </summary> /// <summary> /// MongoDb幫助類 /// </su ...
  • 前面介紹了很多ABP系列的文章,一步一步的把我們日常開發中涉及到的Web API服務構建、登錄日誌和操作審計日誌、字典管理模塊、省份城市的信息維護、許可權管理模塊中的組織機構、用戶、角色、許可權、菜單等內容,以及配置管理模塊,界面的高級查詢處理等內容,同時我們把整個開發理念結合我們的代碼生成工具Data... ...
  • REST 全稱是 Representational State Transfer,有人說它是一種風格,並非一種標準,個人覺得挺有道理。它本身並沒有創造新的技術、組件與服務,更像是告訴大家如何更好地使用現有Web標準中的一些準則和約束,也不可否認,RESTFul 是目前最流行的 API 設計規範,用於 ...
  • ImageSharp是對NetCore平臺擴展的一個圖像處理方案,以往網上的案例多以生成文字及畫出簡單圖形、驗證碼等方式進行探討和實踐。 今天我分享一下所在公司項目的實際應用案例,導出微信二維碼圖片,圓形頭像等等。 一、源碼獲取 Git項目地址:https://github.com/SixLabor ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...