动态生成表达式树插件 Sy.ExpressionBuilder,向着手写条件说拜拜。

  CURD中,基础查询我感觉还是很烦人的一个浪费时间的工作,我经历过远古时代的GetAll(string name,int age),这种方式写服务的时候真的是心中一万个草泥马飞过,后面逐渐的变成了传一个实体GetAll([FromQuery] GetDto)似乎也能默默的忍受,然后含泪写着一堆的WhereIf,目前这种方式应该还是很多人在用的一种方式。然而 Sy.ExpressionBuilder(大家可以去nuget下载试用)的出现,我们有了更好的选择。 

      为了方便后面的介绍,先让我们有几个实体,用户表,角色表,系统表,我们约定一个用户只有一种角色,但是可以存在多个系统中。
     

 /// <summary>
    /// 用户表
    /// </summary>
    public class Manager
    {
        /// <summary>
        /// 编号
        /// </summary>
        public string Id { get; set; }

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

        /// <summary>
        /// 手机
        /// </summary>
        public string Tel { get; set; }

        /// <summary>
        /// 角色编号
        /// </summary>
        public string RoleId { get; set; }

        /// <summary>
        /// 角色
        /// </summary>
        public Role Role { get; set; }


        /// <summary>
        /// 系统
        /// </summary>
        public List<Sys> Sys { get; set; }

        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime CreateTime { get; set; }

        /// <summary>
        /// 性别
        /// </summary>
        public EnumGender Gender { get; set; }
    }
/// <summary>
    /// 角色表
    /// </summary>
    public class Role
    {
        /// <summary>
        /// 角色名
        /// </summary>
        public string RoleName { get; set; }

        /// <summary>
        /// 角色编号
        /// </summary>
        public string Id { get; set; }


    }
    /// <summary>
    /// 系统表
    /// </summary>
    public class Sys
    {
        /// <summary>
        /// 系统名称
        /// </summary>
        public string SysName { get; set; }

        /// <summary>
        /// 编号
        /// </summary>
        public string Id { get; set; }
    }
    /// <summary>
    /// 性别
    /// </summary>
    [Flags]
    public enum EnumGender
    {
        /// <summary>
        /// 男
        /// </summary>
        Man = 1 << 0,


        /// <summary>
        /// 女
        /// </summary>
        Women = 1 << 1,
    }

然后我们先创建张三李四两个小伙伴

            List<Manager> list = new List<Manager>();
            List<Sys> Sys = new List<Sys>();
            List<Sys> Sys2 = new List<Sys>();
            Sys.Add(new Tests.Sys { Id = "1", SysName = "仓管系统" });
            Sys.Add(new Tests.Sys { Id = "2", SysName = "人力资源系统" });
            Sys2.Add(new Tests.Sys { Id = "1", SysName = "仓管系统" });

            list.Add(new Manager { Id = "1", UserName = "张三", Tel = "18888888888", Gender = EnumGender.Man, RoleId = "1", CreateTime = DateTime.Parse("2021-9-22 10:50:50"), Sys = Sys, Role = new Role { RoleName = "超级管理员", Id = "1" } });
            list.Add(new Manager { Id = "2", UserName = "李四", Tel = "16666666666", Gender = (EnumGender)3, RoleId = "2", CreateTime = DateTime.Parse("2021-9-21 10:50:50"), Sys = Sys2, Role = new Role { RoleName = "管理员", Id = "2" } });

数据结构图

在做查询前先让我们定义查询的Dto

 /// <summary>
    /// 查询参数实体
    /// </summary>

    public class AllManagerDto : QueryBase
    {
        /// <summary>
        /// 创建时间 开始(时间必须以Start结尾)
        /// </summary>
        public DateTime? CreateTimeStart { get; set; }

        /// <summary>
        /// 创建时间  结束(结束时间必须以End结尾)
        /// </summary>
        public DateTime? CreateTimeEnd { get; set; }
        /// <summary>
        /// 创建时间(或者使用特性,约定方式)传值为("2021-9-21,2021-10-7")中间用,分割
        /// </summary>
        [Condition("CreateTime", EnumCondition.Between)]
        public string CreateTime { 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 AA { get; set; }
        /// <summary>
        /// 年龄 开始(必须以Min结尾)
        /// </summary>
        public int? AgeMin { get; set; }

        /// <summary>
        /// 年龄  结尾(必须以Max结尾)
        /// </summary>
        public int? AgeMax{ get; set; }
 

    }

我们来做一个简单的单表查询,查询完全满足,名字叫张三,号码为 18888888888,性别男,角色编号为“1”的,创建时间 大于 "2021-9-22" 的用户。我们只需要一句话就可以了,想想你以前的得写多少语句。

我们默认有以下约定 时间格式范围为 <=和>= ,数字 int decimal double等为 <=和>=,string 为包含
 

  /// <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.ToQueryModel<Manager>();
            return list.AsQueryable().Where(query).ToList();
        }

我们看看效果

 生成的表达式

 返回结果,是不是很神奇。

 那如果我们要关联表查询呢,怎么破,别急,看下面代码
 

       /// <summary>
        /// 角色名称
        /// </summary>

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

        public string RoleName { get; set; }


        /// <summary>
        /// 系统名称
        /// </summary>

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

        public string SysName { get; set; }

我们使用 Condition 特性,标识 Role.RoleName 表示 查询Role下 RoleName 等于我们要查的数据,Sys[SysName]  表示用户表下Sys数组下名称为SysName 的条件

这就基本包含了我们所用到的情况。你是不是觉得漏了点什么,我们要处理排序怎么处理,别急,我们内置了添加排序的方法,我们还可以添加多个,完美把

  /// <summary>
        /// 添加排序条件
        /// </summary>
        /// <returns></returns>
        public static BaseQueryModel AddOrderByItem(this BaseQueryModel queryModel, string propName, bool isDesc = true)
        {
            queryModel.OrderByItems.Add(new OrderByItem { PropName = propName, IsDesc = isDesc });
            return queryModel;
        }

至此,我们的插件的基本用法就差不多了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值