gpt4 book ai didi

c# - 在运行时动态生成谓词

转载 作者:太空宇宙 更新时间:2023-11-03 17:54:35 27 4
gpt4 key购买 nike

不确定这是否完全可行;我发现了一些关于表达式和谓词构建器的内容,但到目前为止,还没有任何内容可以让您在事先不知道的情况下运行任意查询。

基本上,我有一个大型 SQL 数据库中的对象集合,我正在构建一个网页 (ASP.NET MVC 4) 以允许用户显示和过滤这些对象。用户将输入的查询的复杂性会有所不同。让他们输入这些查询的最简单、最巧妙的方式类似于 Visual Studio TFS 插件让您搜索工作项的方式:一个条件表,您可以在其中不断添加行。您为连接条件选择“和”或“或”,然后选择一个字段,输入一个值,然后选择您想要匹配还是不匹配的东西:

1. show items where [Field] [is|is not] [value]
2. [and|or] [Field] [is|is not] [value]
3. [and|or] [Field] [is|is not] [value]
etc...

将其转换为 LINQ-ish 的东西的最简单方法是什么,我可以在其末尾粘贴 .ToList()?到目前为止,我提出的唯一解决方案涉及一个相当大且丑陋的开关 block ,其中包含用于匹配各个字段的案例并附加在 .Where() 上,但允许用户选择“或”对于一个条件,然后我最终会做这样的事情:

  • 当条件为 AND 时:
    • 使用big switch匹配字段
    • query = query.Where(ThisField == value);
  • 当您遇到 OR 条件时:
    • 将当前结果附加到临时列表
    • 来自完整未过滤列表的新查询
    • 使用big switch匹配字段
    • query = fullList.Where(ThisField == value);
    • 像以前一样继续
  • 当条件用完时,将当前结果集附加到您一直使用的临时列表,然后返回该列表。

这似乎没有我想要的那么优雅。

最佳答案

你可以这样做:

class Program
{
public enum Operator
{
And,
Or
}

public class Condition
{
public Operator Operator { get; set; }
public string FieldName { get; set; }
public object Value { get; set; }
}

public class DatabaseRow
{
public int A { get; set; }
public string B { get; set; }
}

static void Main(string[] args)
{
var conditions = new List<Condition>
{
new Condition { Operator = Operator.And, FieldName = "A", Value = 1 },
new Condition { Operator = Operator.And, FieldName = "B", Value = "Asger" },
new Condition { Operator = Operator.Or, FieldName = "A", Value = 2 },
};

var parameter = Expression.Parameter(typeof (DatabaseRow), "x");
var currentExpr = MakeExpression(conditions.First(), parameter);
foreach (var condition in conditions.Skip(1))
{
var nextExpr = MakeExpression(condition, parameter);
switch (condition.Operator)
{
case Operator.And:
currentExpr = Expression.And(currentExpr, nextExpr);
break;
case Operator.Or:
currentExpr = Expression.Or(currentExpr, nextExpr);
break;
default:
throw new ArgumentOutOfRangeException();
}
}

var predicate = Expression.Lambda<Func<DatabaseRow, bool>>(currentExpr, parameter).Compile();

var input = new[]
{
new DatabaseRow {A = 1, B = "Asger"},
new DatabaseRow {A = 2, B = "Hans"},
new DatabaseRow {A = 3, B = "Grethe"}
};

var results = input.Where(predicate).ToList();
}

static BinaryExpression MakeExpression(Condition condition, ParameterExpression parameter)
{
return Expression.Equal(
Expression.MakeMemberAccess(parameter, typeof (DatabaseRow).GetMember(condition.FieldName)[0]),
Expression.Constant(condition.Value));
}
}

这假设您有一个类作为具有正确类型的数据库行的模型。然后,您可以通过正则表达式将您的条件解析为上面显示的类型化条件列表,提供的代码可以将其转换为表达式树。生成的表达式可以编译和运行(如图所示)或转换为 SQL(只需将谓词填充到 IQueryable.Where 中)。

关于c# - 在运行时动态生成谓词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14835090/

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