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

ops/2025/2/1 7:06:54/

初识表达式树

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

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

var param = Expression.Parameter(typeof(User), "u");

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

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

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

var method = Expression.Call(param, typeof(User).GetMethod("ToString"));

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

var constant = Expression.Constant(42);

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

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)来构建复合条件表达式:

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 等),我们可以动态地构建表达式树。这种方式使得我们能够灵活地生成查询条件或操作逻辑,特别是在需要构建动态查询或条件时非常有用。


http://www.ppmy.cn/ops/154675.html

相关文章

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.24 随机宇宙:生成现实世界数据的艺术

1.24 随机宇宙&#xff1a;生成现实世界数据的艺术 目录 #mermaid-svg-vN1An9qZ6t4JUcGa {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-vN1An9qZ6t4JUcGa .error-icon{fill:#552222;}#mermaid-svg-vN1An9qZ6t4JUc…

MySQL为什么默认引擎是InnoDB ?

大家好&#xff0c;我是锋哥。今天分享关于【MySQL为什么默认引擎是InnoDB &#xff1f;】面试题。希望对大家有帮助&#xff1b; MySQL为什么默认引擎是InnoDB &#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 MySQL 默认引擎是 InnoDB&#xff0c;主要…

《网络安全中的“泛洪”攻击:揭秘、防范与应对策略》

各类泛洪攻击总结 IPV4泛洪 一、什么是泛洪? 泛洪的基本原理就是基于协议通信&#xff0c;完成大流量高并发操作&#xff0c;导致目标主机各类资源消耗过多而无法提供正常的服务。基于多线程或多进程&#xff08;MAC地址泛洪&#xff0c;ARP泛洪欺骗&#xff09;。 (1) 攻击…

Flink (十二) :Table API SQL (一) 概览

Apache Flink 有两种关系型 API 来做流批统一处理&#xff1a;Table API 和 SQL。Table API 是用于 Scala 和 Java 语言的查询API&#xff0c;它可以用一种非常直观的方式来组合使用选取、过滤、join 等关系型算子。Flink SQL 是基于 Apache Calcite 来实现的标准 SQL。无论输入…

leetcode 面试经典 150 题:有效的括号

链接有效的括号题序号20题型字符串解法栈难度简单熟练度✅✅✅ 题目 给定一个只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&#xff0c;‘[’&#xff0c;‘]’ 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须…

「全网最细 + 实战源码案例」设计模式——生成器模式

核心思想 生成器模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;用于分步骤构建复杂对象&#xff0c;允许用户通过控制对象构造的过程&#xff0c;定制对象的组成部分&#xff0c;而无需直接实例化它们的细节。建造者模式特别适合构建具有多种配…

python3+TensorFlow 2.x(四)反向传播

目录 反向传播算法 反向传播算法基本步骤&#xff1a; 反向中的参数变化 总结 反向传播算法 反向传播算法&#xff08;Backpropagation&#xff09;是训练人工神经网络时使用的一个重要算法&#xff0c;它是通过计算梯度并优化神经网络的权重来最小化误差。反向传播算法的核…

vue3第三部分--组件通信

title: 组件通信 date: 2025-01-28 12:00:00 tags:- 前端 categories:- 前端组件通信 目标&#xff1a;重点学习父子组件与兄弟组件的通信方式&#xff0c;以及插槽的作用与使用方式 父子组件通信 主要是通过props和自定义事件来实现 1.1 父 -> 子通信&#xff08;通过 …