gpt4 book ai didi

c# - IQueryable:动态创建 OR 过滤

转载 作者:行者123 更新时间:2023-11-30 17:21:07 26 4
gpt4 key购买 nike

我有一组这种形式的搜索条件:

 member  |  value  |  operator
--------+---------+---------
height | 10 | >
height | 2 | <
name | Carl | ==

我想查询所有符合这些条件的对象。

现在,我正在通过:

  • 为每一个建立一个表达式的标准
  • 使用“或”连接每个表达式表达
  • 构建一个lambda表达式包含连接表达式
  • 将 lambda 表达式传递给 IQueryable<>.Where() 方法

您知道使用连续 OR 动态过滤 IQueryable 集合的最简单方法吗?


奖金我们的解决方案:

基于 IlyaBuiluk solution @ CodeProject

// The structure used by the new extension method
public struct SearchCriteria
{
public string Column;
public object Value;
public WhereOperation Operation;
}

// How to convert the rules structure to the search criteria structure
var searchCriterias = grid.Where.rules.Select(Rule => new SearchCriteria
{
Column = Rule.field,
Operation =
(WhereOperation)
StringEnum.Parse(
typeof (WhereOperation),
Rule.op),
Value = Rule.data
}).ToArray();


// Usage:
query = query.WhereOr(searchCriterias);


// Implementation
public static IQueryable<T> WhereOr<T>( this IQueryable<T> Query, SearchCriteria [ ] Criterias )
{
if( Criterias.Count( ) == 0 )
return Query;

LambdaExpression lambda;
Expression resultCondition = null;

// Create a member expression pointing to given column
ParameterExpression parameter = Expression.Parameter( Query.ElementType, "p" );

foreach( var searchCriteria in Criterias )
{
if( string.IsNullOrEmpty( searchCriteria.Column ) )
continue;

MemberExpression memberAccess = null;
foreach( var property in searchCriteria.Column.Split( '.' ) )
memberAccess = MemberExpression.Property
( memberAccess ?? ( parameter as Expression ), property );

// Change the type of the parameter 'value'. it is necessary for comparisons (specially for booleans)
ConstantExpression filter = Expression.Constant
(
Convert.ChangeType( searchCriteria.Value, memberAccess.Type )
);

//switch operation
Expression condition = null;
switch( searchCriteria.Operation )
{
//equal ==
case WhereOperation.Equal:
condition = Expression.Equal( memberAccess, filter );
break;
//not equal !=
case WhereOperation.NotEqual:
condition = Expression.NotEqual( memberAccess, filter );
break;
// Greater
case WhereOperation.Greater:
condition = Expression.GreaterThan( memberAccess, filter );
break;
// Greater or equal
case WhereOperation.GreaterOrEqual:
condition = Expression.GreaterThanOrEqual( memberAccess, filter );
break;
// Less
case WhereOperation.Less:
condition = Expression.LessThan( memberAccess, filter );
break;
// Less or equal
case WhereOperation.LessEqual:
condition = Expression.LessThanOrEqual( memberAccess, filter );
break;
//string.Contains()
case WhereOperation.Contains:
condition = Expression.Call( memberAccess,
typeof( string ).GetMethod( "Contains" ),
Expression.Constant( searchCriteria.Value ) );
break;

default:
continue;
}

resultCondition = resultCondition != null ? Expression.Or( resultCondition, condition ): condition;
}

lambda = Expression.Lambda( resultCondition, parameter );

MethodCallExpression result = Expression.Call(
typeof( Queryable ), "Where",
new [ ] { Query.ElementType },
Query.Expression,
lambda );

return Query.Provider.CreateQuery&lt;T&gt;( result );

}

最佳答案

如果您有一组固定的运算符和一组固定的成员,那么您几乎可以在不直接处理表达式树的情况下编写它。这个想法是为各种代码片段创建简单的 lambda 表达式(例如 Expression<Func<Entity, string>> 用于读取成员的属性和类似的运算符),然后将它们组合起来构建一个表达式树。我 described the solution here .唯一的问题是 C# 不直接支持组合表达式,因此您需要进行一些预处理(请参阅有关“可扩展实用程序”的部分)。

然后您可以将基本功能存储在字典中,并根据用户选择的内容选择正确的功能(或它们的组合)。例如:

NorthwindDataContext db = new NorthwindDataContext();

// A query that tests whether a property
// (specified by 'selector' matches a string value
var queryBuilder = Linq.Func
((Expression<Func<Customer, string>> selector, string val) =>
from c in db.Customers.ToExpandable()
where selector.Expand(c).IndexOf(val) != -1
select c);

// Dictionary with supported members...
var dict = new Dictionary<string, Expression<Func<Customer, string>>>
{ { "CompanyName", c => c.CompanyName },
{ "Country", c => c.Country },
{ "ContactName", c => c.ContactName } };

// Ask user for a property name & value and Build the query
string field = Console.ReadLine();
string value = Console.ReadLine();
var q = queryBuilder(dict[field], value);

本文还包含一个动态组合 OR 或 AND 条件的示例。我有一段时间没有更新代码,所以它需要一些工作,但我相信 LINQ KIT项目也包含这个想法的一个版本。

关于c# - IQueryable:动态创建 OR 过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3712803/

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