【问题标题】:What's the usecase of expression tree?表达式树的用例是什么?
【发布时间】:2021-12-19 12:25:48
【问题描述】:

我已阅读以下内容:https://stackoverflow.com/a/20766203/10046099

我没有得到的是这部分:

创建表达式树是为了完成转换任务 将诸如查询表达式之类的代码转换为可以传递给的字符串 其他一些过程并在那里执行。就是这么简单。

如果我们得到了查询表达式,为什么不能直接将其转换成 sql 字符串发送到 sql 数据库?为什么需要树?因为它不是直接将查询表达式转换为sql字符串,而是先将其转换为树,然后将树转换为sql字符串,这意味着2步而不是1。

我希望得到最简单的解释。

更新

我们看下面的linq

 IEnumerable<int> scoreQuery =
            from score in scores
            where score > 80
            select score;

你能把它变成二叉树图的表达式树吗?也许在此之后,我会更容易将表达式树转换为 sql 字符串。

【问题讨论】:

  • "如果我们得到了查询表达式,为什么不能直接将其转换成 sql 字符串发送到 sql 数据库?" - 你期望这样做的“它”是什么? C# 编译器将 lambda 表达式视为源代码,但如果 C# 编译器必须了解 SQL,这将严重违反关注点分离。 (除了 SQL,可以使用当前架构处理的东西呢?您是否建议将 everything 捆绑在 C# 编译器中?如果您想支持 C# 编译器团队的查询语言怎么办?不喜欢?)
  • 这意味着 2 个步骤而不是 1 个步骤 - 我有点好奇为什么你认为它是一件坏事。毕竟,当您编写 C# 时,CPU 不会运行 C#。它会在变成一堆 0 和 1/电压电平之前被转换很多次,所以你必须明白,在你的一生中,由于各种原因,中间步骤真的很方便——不仅仅是英特尔与 ARM CPU 或 WIndows 与 Linux。即使结果是,在数学考试中展示你的工作至少可以让你得到一些分数错误的。铁矿石冶炼厂不生产汽车。总体而言,直接从 A 到 Z 通常是个坏主意
  • 您发布的语句不是 LINQ 表达式。它包含两个 LINQ 表达式:score &gt; 80score
  • @IanMercer 我想了解如果 Linq 转换为表达式树,表达式树如何知道如何将其转换为特定的 sql 数据库?它可能是 sql、postgresql、mysql 或任何最终可能具有不同语法的东西。 ?
  • 如果您看不到某个功能的用途,我通常会建议您将其放在“可能很有趣,但现在与我无关”的堆中。稍后,如果您遇到问题并且有人为您提供了使用该功能的解决方案,您将有一个真实、令人信服、与相关的理由来说明它为什么有用。同时,您无需要求其他人证明该功能的存在是合理的。也许它永远不会与你相关——那也没关系。

标签: c# sql linq lambda


【解决方案1】:

如果我们有查询表达式,为什么不能直接转换成sql字符串

你会使用什么 SQL 方言?这意味着 LINQ 系统基本上必须包含所有可能的 SQL 方言生成器。

此外,您将无法通过多个步骤生成表达式树。是的,这是一件事 - 生成第一个 where,然后在长长的 if 条件列表中添加 where 子句。

通过生成表达式树,您不仅可以在生成 SQL 之前对其进行操作,还可以让 SQL 生成由更下方的适配器完成。这样您就可以支持所有 SQL 方言。

【讨论】:

  • 非常感谢。我更新了问题。
  • 它引起了更多的混乱,这就是原因。一般来说,我最终会这样做:似乎提供者可以更容易地将表达式树转换为 sql 字符串,而不是提供者可以将直接 Linq 表达式转换为 sql 字符串。不知道为什么。再次抱歉
【解决方案2】:

编译器将你的代码转换成

IEnumerable<int> scoreQuery scores.Where(score => score > 80).Select(score => score);

在第二步中,这段代码被转换成

ParameterExpression parameterExpression = Expression.Parameter(typeof(int), "score");
BinaryExpression body = Expression.GreaterThan(parameterExpression, Expression.Constant(80, typeof(int)));
ParameterExpression[] array = new ParameterExpression[1];
array[0] = parameterExpression;
Expression<Func<int, bool>> whereExpression = Expression.Lambda<Func<int, bool>>(body, array);

parameterExpression = Expression.Parameter(typeof(int), "score");
ParameterExpression body2 = parameterExpression;
ParameterExpression[] array2 = new ParameterExpression[1];
array2[0] = parameterExpression;
Expression<Func<int, int>> selectExpression = Expression.Lambda<Func<int, int>>(body2, array2);

IEnumerable<int> scoreQuery scores.Where(whereExpression).Select(selectExpression);

这是信息的方式,例如应检查是否存储了分数大于 80。基本上,您可以像上面那样直接编写代码,但它更费力且更难阅读,这就是编译器提供上述单行代码的缩写的原因。

在运行时,实体框架或任何其他 ORM 工具将分析上面的表达式树。它将使用存储在那里的信息来构建 SQL 查询。例如,因为 where 表达式的 NodeTypeExpresionType.GreaterThan,EF 将在 SQL 查询中使用 &gt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多