gpt4 book ai didi

c# - 构建可动态转换为有效 SQL 的表达式树,可以将字符串与 double 值进行比较

转载 作者:太空狗 更新时间:2023-10-29 21:49:01 25 4
gpt4 key购买 nike

我在 SQL Server 中有下表:

产品属性

  • 名称:nvarchar(100)
  • 值:nvarchar(200)

这是通过 Entity Framework 映射到我的类中的:

public class ProductAttribute
{
public string Name {get;set;}
public string Value {get;set;}
}

ProductAttributes 的某些行具有以下形式:

  • {名称:“RAM”,值:“8 GB”},{名称:“缓存”,值:“3000KB”}

我需要动态构建一个可转换为 SQL 的 ExpressionTree,它可以执行以下操作:

  • 如果值以数字开头,后跟或不后跟字母数字字符串,则提取该数字并将其与给定值进行比较

    double value = ...;

    Expression<Func<ProductAttribute, bool>> expression = p =>
    {
    Regex regex = new Regex(@"\d+");
    Match match = regex.Match(value);

    if (match.Success && match.Index == 0)
    {
    matchExpression = value.Contains(_parserConfig.TokenSeparator) ?
    value.Substring(0, value.IndexOf(_parserConfig.TokenSeparator)) :
    value;

    string comparand = match.Value;
    if(double.Parse(comparand)>value)
    return true;
    }

    return false;
    }

真正令人讨厌的是我需要动态构建这个表达式树

到目前为止,我已经做到了这一点(它将值视为小数而不是字符串,因此它甚至不会尝试执行整个正则表达式):

private Expression GenerateAnyNumericPredicate(
Type type,
string valueProperty,
string keyValue,
double value) {
ParameterExpression param = Expression.Parameter(type, "s");
MemberExpression source = Expression.Property(param, valueProperty);
ConstantExpression targetValue = GetConstantExpression(value, value.GetType());
BinaryExpression comparisonExpression = Expression.GreaterThan(source, targetValue);

return Expression.Lambda(comparisonExpression, param);
}

编辑:在下面提供的帮助下,这是可行的:

  Expression<Func<ProductSpecification, bool>> expo = ps=> ps.Value.Substring(0, (SqlFunctions.PatIndex("%[^0-9]%", ps.Value + ".") ?? 0) - 1) == "1000";

但我还需要转换为 double,然后进行数字比较:

  Expression<Func<ProductSpecification, bool>> expo = ps=> double.Parse(ps.Value.Substring(0, (SqlFunctions.PatIndex("%[^0-9]%", ps.Value + ".") ?? 0) - 1)) > 1000;

显然这不能转换为 SQL:double.Parse()

我如何构造转换以便从我的表达式中将其解析为 SQL?

最佳答案

我认为 Yacoub Massad 询问 SQL 应该是什么样子是有道理的。如果没有办法编写执行查询的 SQL,怎么可能有转换为所需 SQL 的表达式树?

主要问题是 SQL Server 本身不支持正则表达式。您可以将 CLR 函数导入数据库并在 UDF 中使用它,但这并不是使其与 EF 一起工作的最简单方法。

因此,同样地,从想象可以完成这项工作的 SQL 开始。

现在我找到了this从字符串中提取数字(左)部分的小 gem:

select left(@str, patindex('%[^0-9]%', @str+'.') - 1)

这将从“3000KB”返回“3000”。

幸运的是,我们可以使用SqlFunctions.PatIndex在 LINQ 语句中重现此内容:

from pa in context.ProductAttributes
select pa.Value.Substring(0, (SqlFunctions.PatIndex("%[^0-9]%", pa.Value + ".") ?? 0) - 1)

这显然会从您的示例中返回 83000

现在困难的部分已经完成,您可以使用此结果将谓词应用于此数字部分:

from pa in context.ProductAttributes
let numPart = pa.Value.Substring(0, (SqlFunctions.PatIndex("%[^0-9]%", pa.Value + ".") ?? 0) - 1)
where numPart .... // go ahead

你会看到,每次在 LINQ 语句中使用 numPart 时,整个 PatIndex 内容都会在 SQL 语句中重复(即使你换行它在子查询中)。不幸的是,这就是 SQL 的工作原理。它不能存储临时的报表内结果。好吧,语言规范已有 40 多年历史,一点也不差。

关于c# - 构建可动态转换为有效 SQL 的表达式树,可以将字符串与 double 值进行比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38446268/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com