关于ExpressionTree的一点儿想法

本文介绍如何利用Expression表达式树实现动态拼接查询条件,避免修改后台代码。通过.NET中的MogoDb插件,实现了灵活的前端查询条件组合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

其实第一次接触到ExpressionTree的时候,大概是在四年前,在面试的时候,有人问我,我们有一个前端页面,增加了查询条件,但是却不想变更后台代码,应该怎样处理,苦思冥想很久,想到了如下代码:

1、封装对象

 public class OperateObj
 {
        /// <summary>
        /// 条件
        /// </summary>
        public string Condition { get; set; }


        /// <summary>
        /// 条件
        /// </summary>
        public OperateType OperateType { get; set; }

        /// <summary>
        /// 值
        /// </summary>
        public string Value { get; set; }
    }

    public enum OperateType
    {
        Add=1,
        Subtraction=2,
        Multiplication=3,
        Division=4,
        Equal=5
    }

2、将所有前台的条件都转换为OperateObj对象,并添加到List数组中,如遇到Name=“张三”这样的条件

则转换为:

List<OperateObj> arrObj = new List<OperateObj>();
 arrObj.Add(new OperateObj()
{
       Condition = "Name",
       OperateType = OperateType.Equal,
       Value="张三"
});

将这样的条件映射到后台后,根据这样的数组,重新拼接为Sql语句,

如:原始的Sql语句为:

select * from UserInfo where DepartmentName=“销售部”

根据数组转换为:

select * from UserInfo where DepartmentName=“销售部” and Name=“张三”;

由于是刚毕业时的面试题,尽管回答的牵强,依然获得了一次面试通过的机会,后来我了解到Expression表达式。了解到Expression表达式树之后,才发现之前的回答真的仅仅算是牵强。

一直没有机会总结,因为懒,直到最近在使用MogoDB的再次接触到Expression,同样遇到了拼接条件的问题,在开发的时候,大家一定发现用户在前端查询的条件永远是不确定的,也许一个都不输入,也许是其中某几个查询条件的随机组合。

当然,我们在使用MogoDb时用于使用了.Net中关于MogoDb的插件动态链接库MongoDB.Driver,在这个动态链接库中封装了Expression表达式的查询方式,省了大量的组织MogoDB查询封装的工作。虽然免了直面数据库查询的工作,但依然无法逃避组织查询条件的工作。故,结合之前的学习以及现在的工作,特将Expression表达式树总结一下:

结合自己的也许需求:

我们需要查询这样结构的数据对象:

 public class QrCodeItems : BaseEntity
    {
        /// <summary>
        /// 
        /// </summary>
        public string EwmCode { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public string Batch { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public string PrizeName { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public int PrizeFlag { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public string FirstUserId { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public DateTime? FirstDate { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public string CurrentUserId { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public DateTime? CurrentDate { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public string DriverId { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public DateTime? DriverScanDate { get; set; }

        /// <summary>
        /// 0未扫,1已扫,2已兑,3结束
        /// </summary>
        public int CurrentStage { get; set; }

        /// <summary>
        /// 码值所属区域
        /// </summary>
        public string Source { get; set; }
    }

所有查询字段都基于该对象,在实际业务中,我们也可以根据数据表结构的字段反射为对象。

ok,我们现在定义最基础的查询条件,Expreesion表达式跟Sql语句一样,我们也会遇到第一个字符串拼接Where 还是拼接And

ParameterExpression param = Expression.Parameter(typeof(QrCodeItems));
            Expression filter = null;
            Expression left = null;
            Expression right = null;
            if (!string.IsNullOrWhiteSpace(source))
            {
                left = Expression.Property(param, "Source");
                right = Expression.Constant(source);
                filter = Expression.Equal(left, right);
            }
//二维码状态
            if (!string.IsNullOrWhiteSpace(stage) && stage != "-1")
            {
                left = Expression.Property(param, "CurrentStage");
                right = Expression.Constant(Convert.ToInt32(stage));
                filter = Expression.And(filter, Expression.Equal(left, right));
            }

我们将所有条件拼接完成之后,转换为Lambda表达式即可:

Expression<Func<QrCodeItems, bool>> where = Expression.Lambda<Func<QrCodeItems, bool>>(filter, param);//生成最后需要的带参数的表达式树.

就这样,我们动态拼接条件的目的就达到了,当然这不是最终代码,我们还可以根据这段代码继续优化,以及我们的目的是探讨Expression表达式树的最底层架构,

下文再说。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值