超簡單的集成表達式樹查詢組件,Sy.ExpressionBuilder 使用說明


    Sy.ExpressionBuilder是一套依賴於表達式樹上的集成的查詢組件。設計的初衷沒別的,就為了少寫代碼,讓查詢業務可以變得更加模式化。可以從nuget 獲取到該組件。

    來到查詢,查詢實體需要繼承  QueryPageModel或者 QueryModel,從名字也基本可以看出來,一個用於分頁,一個無分頁,你可以根據自己需求選用哪個方式,如下我選了帶分頁的方式。

public partial class AllManagerDto:QueryPageModel

   這樣這個查詢實體就擁有了我們這個插件的大多數功能。

    屬性名稱約束
    為了方便處理各種屬性類型,我做了一些屬性名稱的約定。 

    時間范圍查詢 =>屬性名稱 以  Start,End 結尾 ,生成條件為 >= 和<=。
    數字范圍查詢 =>屬性名稱 以  Min,Max 結尾 ,生成條件為 >= 和<=。
    字符串查詢 => 名字需要和表字段一致,生成條件為  Contains。

    編號查詢必須是以Id結尾,不然如果編號為字符串的話,查詢方式會以Contains形式查詢。

    
    例如:

 /// <summary>
        /// 租戶編號
        /// </summary>
        public virtual int? TenantIdMin { get; set; }
        /// <summary>
        /// 租戶編號
        ///</summary>
        public virtual int? TenantIdMax { get; set; }
        /// <summary>
        /// 創建時間
        /// </summary>
        public virtual DateTime? CreateTimeStart { get; set; }
        /// <summary>
        /// 創建時間
        ///</summary>
        public DateTime? CreateTimeEnd { get; set; }
        /// <summary>
        /// 創建人編號
        /// </summary>
        public virtual string? CreateUserId { get; set; }
View Code

    特性約束
    應用ConditionAttribute 特性,參數為 (字段名稱,條件,查詢方式)  目前我定義了常用的范圍的約束。范圍類型枚舉       

/// <summary>
    /// 高級搜索條件
    /// </summary>
    [Description("高級搜索條件")]
    public enum EnumCondition
    {
        /// <summary>
        /// 包含
        /// </summary>
        [Description("包含")]
        Contains = 0,

        /// <summary>
        /// 等於
        /// </summary>
        [Description("等於")]
        Equal = 1,

        /// <summary>
        /// 大於等於
        /// </summary>
        [Description("大於等於")]
        GtEqual = 2,

        /// <summary>
        /// 大於
        /// </summary>
        [Description("大於")]
        Gt = 3,

        /// <summary>
        /// 小於等於
        /// </summary>
        [Description("小於等於")]
        LtEqual = 4,

        /// <summary>
        /// 小於
        /// </summary>
        [Description("小於")]
        Lt = 5,


        /// <summary>
        /// 不等於
        /// </summary>
        [Description("不等於")]
        NotEqual = 6,


        /// <summary>
        /// SQL(In函數)
        /// </summary>
        [Description("SQL In")]
        In = 7,

        /// <summary>
        /// 在什么之間
        /// </summary>
        [Description("在什么之間")]
        Between = 8,

        /// <summary>
        /// 不包含
        /// </summary>
        [Description("不包含")]
        NotContain = 9,

        /// <summary>
        /// 從尾部匹配
        /// </summary>
        [Description("從尾部匹配")]
        EndsWith = 10,

        /// <summary>
        /// 從頭部匹配
        /// </summary>
        [Description("從頭部匹配")]
        StartsWith = 11,

        /// <summary>
        /// 不在范圍內
        /// </summary>
        [Description("不在范圍內")]
        NotIn = 12,

        /// <summary>
        /// 空的
        /// </summary>
        [Description("空的")]
        IsEmpty = 13,

        /// <summary>
        /// 不為空的
        /// </summary>
        [Description("不為空的")]
        IsNotEmpty = 14,

        /// <summary>
        /// 非Null的
        /// </summary>
        [Description("非Null的")]
        IsNotNull = 15,

        /// <summary>
        /// Null的
        /// </summary>
        [Description("Null的")]
        IsNull = 16,

        /// <summary>
        /// IsNullOrWhiteSpace
        /// </summary>
        [Description("IsNullOrWhiteSpace")]
        IsNullOrWhiteSpace = 17,

        /// <summary>
        /// IsNotNullNorWhiteSpace
        /// </summary>
        [Description("IsNotNullNorWhiteSpace")]
        IsNotNullNorWhiteSpace = 18,

        /// <summary>
        /// 
        /// </summary>
        [Description("枚舉")]
        HasFlag = 19,

    }
View Code

   當然我們怎么會少得了查詢方式(且和或)的約束,這就放上來

  /// <summary>
    /// 當前條件所屬類型
    /// </summary>
    [Description("當前條件所屬類型")]
    public enum EnumConditionType
    {
        /// <summary>
        ////// </summary>
        [Description("")]
        And = 0,

        /// <summary>
        ////// </summary>
        [Description("")]
        Or = 1
    }
View Code

  這樣就構成了我們的查詢約束,一般情況下,當前表字段查詢的話我們只要屬性名和表字段名一直即可,例如查詢用戶表的下UserName,如下即可

    /// <summary>
    /// 用戶名稱
    /// </summary>
    public string? UserName { get; set; }

  如果有那種不想暴露字段在外部的,這時我們的特性才會說顯示出用戶,例如我還是要查詢UserName,但是暴露給前端的名稱確是Uname,因為特性中的屬性名優先級會高於查詢模型中的名稱,那我們可如下處理

   [Condition("UserName", EnumCondition.Contains,EnumConditionType.And)]
    public string?Uname { get; set; }

 又或者我們的某個字段需要包含一個集合的情況,我們可以如下實現(傳過來的是用逗號分隔如:1,2,5,6)

   [Condition("UserId",EnumCondition.In,EnumConditionType.And)]
   public string?UserIds{ get; set; }

 導航屬性單個查詢,例如我在用戶表,要根據角色名稱查詢,我們只要如下定義即可(導航屬性名【角色表】+“.”+角色表下的角色名稱,注意這個英文的 .,這個才是精髓)

[Condition($"{nameof(Role)}.{nameof(Role.RoleName)}", EnumCondition.Contains,EnumConditionType.And)] 
public string? RoleName { get; set; }

 導航屬性集合查詢,例如我在角色表,要查詢有分配用戶名字叫老王的所有角色,我們只要如下定義即可(導航屬性名+“[”+角色表下的角色名稱+"]",注意這個英文的 [], [] 表示這個是個集合)
   

[Condition("Users[UserName]", EnumCondition.Contains,EnumConditionType.And)] 
public string? UserName{ get; set; }

 特別說明,該組件還支持位移枚舉的查詢,使用也超級簡單,和一般屬性幾乎無差,查詢模型中如下定義即可。

/// <summary>
/// 性別
/// </summary>
 public EnumGender? Gender { get; set; }

不參與查詢特性

   如果我們有個別參數是作用於別的用途,不直接參數查詢,或者目前該插件處理不了的,我們可以通過該特性排除,如下使用
 

  /// <summary>
  /// 不參與查詢
  /// </summary>
  [NotQuery]
  public string TreeId { get; set; }

 

時間范圍特性(2022年3月21號加)
  當限制用戶查詢時間范圍的時候用,方式如下(特性只用加一個,EnumTimeType 有年月日 時 多種類型可以選擇)

        /// <summary>
        /// 創建時間 開始
        /// </summary>
        [TimeSpan(4,EnumTimeType.Day)]
        public DateTime? CreateTimeStart { get; set; }

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

 

額外擴展
  對於排序,有些情況要做到用戶點擊表頭,然后由后端進行排序后返回,這里我也預留了空間,如下(input 為繼承了:QueryPageModel 的模型),第一個參數表示 要排序的字段名,第二個參數true 表示倒序,false 表示正序。

 

 input.AddOrderByItem(nameof(News.Id),true);

我還加了一個相對顯得雞肋的默認排序(強迫症喜歡有個默認的),如果前端有傳排序過來的話,這個是無效的,使用方式如下:

input.DefaultOrderBy(nameof(News.CreateTime)

 

當我們了解了以上約定,我們定義一個相對完整的查詢模型,如下

 /// <summary>
    /// 查詢參數實體
    /// </summary>

    public class AllManagerDto : QueryPageModel
    {
        /// <summary>
        /// 創建時間 開始(時間必須以Start結尾)
        /// </summary>
        public DateTime? CreateTimeStart { get; set; }

        /// <summary>
        /// 創建時間  結束(結束時間必須以End結尾)
        /// </summary>
        public DateTime? CreateTimeEnd { get; set; }
      
        /// <summary>
        /// 角色編號
        /// </summary>
        [Condition("Role.Id", EnumCondition.In)]
        public string RoleId { get; set; }

        /// <summary>
        /// 角色名稱
        /// </summary>

        [Condition("Role.RoleName", EnumCondition.Contains)]

        public string RoleName { get; set; }


        /// <summary>
        /// 系統名稱
        /// </summary>

        [Condition("Sys[SysName]", EnumCondition.Contains)]

        public string SysName { get; set; }


        /// <summary>
        /// 名稱
        /// </summary>
        public string UserName { get; set; }


        /// <summary>
        /// 性別
        /// </summary>

        public EnumGender? Gender { get; set; }


        [NotMapped]
        public string TreeId { get; set; }

        /// <summary>
        /// 年齡 開始(必須以Min結尾)
        /// </summary>
        public int? AgeMin { get; set; }

        /// <summary>
        /// 年齡  結尾(必須以Max結尾)
        /// </summary>
        public int? AgeMax{ get; set; }
 


    }
View Code

現在我們就可以進行查詢了,如下(留意這句,input.ToExpression<Manager>() 主要是這句把查詢參數轉換成表達式了)

       /// <summary>
        /// 查詢
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static List<Manager> GetAll(AllManagerDto input)
        {
            var list = GetList();
            input.RoleId = "1";
            input.Tel = "18888888888";
            input.UserName = "張三";
            input.Gender = EnumGender.Man;
            input.CreateTimeStart = DateTime.Parse("2021-9-22");
            var query = input.ToExpression<Manager>();
            return list.AsQueryable().Where(query).ToList();
        }

放個以前的效果圖

 后續有擴展,會在這里加.....

 好了,到這你又可以去擼代碼了。

    

    

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM