从CRUD到高级功能:EF Core在.NET Core中全面应用(四)

初识表达式树

表达式树:是一种可以描述代码结构的数据结构,它由一个节点组成,节点表示代码中的操作、方法调用或条件表达式等,它将代码中的表达式转换成一个树形结构,每个节点代表了代码中的操作例如,如果你有一个简单的C#表达式x => x.Name == "John",EFCore会将其转化为一个表达式树,这里我们可以通过Expression构建表达式树,如下所示:

cs 复制代码
Exception<Func<Book, bool>> e1 = b => b.Price > 5;
Exception<Func<Book, double>> e2 = (b1,b2) => b1.Price + b2.Price;

查看表达式树:这里我们可以通过断点调试,鼠标放在e1上面,点击右键点击快速监视,点击DebugView可以看到文本可视化工具, 如下所示:

整个表达式树是一个"或"类型的节点,左节点(Left)是b.Price>5的表达式,右节点(Right)是另外一个表达式,而b.Price>5这个表达式又是一个大于类型的节点 ,当然我们也可以看一下e2,通过快速监视可以看到其节点类型是相加类型,左边是b1右边是b2:

总结:Expression对象存储了运算逻辑,它把运算逻辑保存成抽象语法树(AST),可以在运行时动态获取运算逻辑,而普通委托则没有。

构建表达式树

只有通过代码动态构建表达式树才能更好的发挥表达式树的能力,ParameterExpression、BinaryExpression、MethodCallExpression、ConstantExpression等类几乎都没有提供构造方法,而且所有属性也几乎都是只读的。因此我们一般不会直接创建这些类的实例,而是调用Expression类的Parameter、MakeBinary、Call、Constant等静态方法来生成,这些静态方法我们一般称作创建表达式树的工厂方法,而属性则通过方法参数类设置。

ParameterExpression:表示表达式树中的一个参数,通常用于函数参数或 Lambda 表达式中的参数。

我们不能直接创建 ParameterExpression,而是通过 Expression.Parameter 方法来生成,如下:4

cs 复制代码
var param = Expression.Parameter(typeof(User), "u");

BinaryExpression:表示两个操作数之间的二元操作,例如加法、减法、比较等。我们可以通过 Expression.MakeBinary 方法来构建。

cs 复制代码
var left = Expression.Property(param, "Age");
var right = Expression.Constant(18);
var binaryExpression = Expression.MakeBinary(ExpressionType.GreaterThan, left, right);

MethodCallExpression:表示调用方法的表达式。例如,调用 ToString() 方法。我们通过 Expression.Call 来创建它。

cs 复制代码
var method = Expression.Call(param, typeof(User).GetMethod("ToString"));

ConstantExpression:表示常量的值,通常用于表达式中的常量部分。通过 Expression.Constant 方法来创建。

cs 复制代码
var constant = Expression.Constant(42);

通过组合这些表达式,我们可以构建一个完整的 Lambda 表达式。例如,构建一个 x => x.Age > 18 的表达式:

cs 复制代码
var param = Expression.Parameter(typeof(User), "x");
var ageProperty = Expression.Property(param, "Age");
var ageGreaterThan = Expression.Constant(18);
var condition = Expression.GreaterThan(ageProperty, ageGreaterThan);

var lambda = Expression.Lambda<Func<User, bool>>(condition, param);

通过组合多个表达式,我们可以构建更复杂的表达式。例如,使用逻辑操作符(AND、OR)来构建复合条件表达式:

cs 复制代码
var left = Expression.GreaterThan(Expression.Property(param, "Age"), Expression.Constant(18));
var right = Expression.Equal(Expression.Property(param, "Name"), Expression.Constant("John"));
var combined = Expression.AndAlso(left, right);

var lambda = Expression.Lambda<Func<User, bool>>(combined, param);

总结:通过使用 Expression 类提供的静态工厂方法(如 Expression.Parameter、Expression.MakeBinary、Expression.Call 等),我们可以动态地构建表达式树。这种方式使得我们能够灵活地生成查询条件或操作逻辑,特别是在需要构建动态查询或条件时非常有用。

相关推荐
GEO科技6 小时前
从SEO到GEO:AI时代的品牌大模型种草与数字营销重构
经验分享
会的全对٩(ˊᗜˋ*)و7 小时前
【数据结构】栈
数据结构·经验分享·
zzywxc7878 小时前
如何高效清理C盘、释放存储空间,让电脑不再卡顿。
经验分享·缓存·性能优化·电脑
deming_su12 小时前
企业流程知识:《超越再造:以流程为中心的组织如何改变我们的工作和生活》读书笔记
经验分享
Li Zi10 天前
STM32 ADC(DMA)双缓冲采集+串口USART(DMA)直接传输12位原始数据到上位机显示并保存WAV格式音频文件 收藏住绝对实用!!!
经验分享·stm32·单片机·嵌入式硬件
Heart_to_Yang10 天前
kali2022 系统更新报错:由于没有公钥无法验证下列签名
linux·运维·服务器·经验分享
LaughingZhu10 天前
PH热榜 | 2025-06-23
前端·人工智能·经验分享·搜索引擎·产品运营
IDRSolutions_CN10 天前
在 Java 中生成 PDF 缩略图(教程)
java·经验分享·pdf·软件工程·团队开发
IDRSolutions_CN10 天前
用Java将PDF转换成GIF
java·经验分享·pdf·软件工程·团队开发
LaughingZhu10 天前
PH热榜 | 2025-06-21
前端·人工智能·经验分享·搜索引擎·产品运营