使用动态 linq 从列表<字符串>生成 Linq 查询
本文关键字:字符串 生成 Linq 查询 列表 动态 linq | 更新日期: 2023-09-27 18:36:40
我正在使用动态linq来预处理一些用户请求。 它的设置方式是我将数据收集到 Var 数据中
var data = Project.Model.Adhoc.GetData().AsQueryable();
这基本上是从视图中选择 *
然后从那里我将遍历我必须过滤的用户选择的所有选项
foreach (Filters filter in filters.OrderBy(x=>x.strOrderNumber))
{
除了一些检查和排列,我开始解决这个问题
data = data.Where(filter.strFilter + FormatOperator(filter.strOperator) + "@0", filter.strValue).
Select(x => x).ToList().AsQueryable();
这运行良好,但是数据源开始增长,所以我想做的是这样的:
data = data.select(get all items that were selected)
,然后进行检查和排列。 这将允许我只提取所需的内容,而不是整个数据源。 在 C# 中使用 linq 来实现此目的的最佳方法是什么?
前任。
datasource = {Name, Age, Race, Gender, Hair Color, Eye Color, height, weight, etc}
user selected = {Name, Age, Race, Gender}
我不想查询整个数据源,而是希望将数据源限制为仅用户引入的内容,然后我可以基于该数据源进行筛选
看看动态林克
可以对任何 LINQ 数据提供程序使用 DynamicQuery 库 (包括 LINQ to SQL、LINQ to Objects、LINQ to XML、LINQ to 实体、LINQ to SharePoint、LINQ to TerraServer 等)。 而不是 使用语言运算符或类型安全的 Lambda 扩展方法来 构造您的 LINQ 查询,动态查询库为您提供 使用基于字符串的扩展方法,您可以传递任何字符串 表达成。
删除 foreach 循环中的.ToList()
调用。
data = data.Where()
将使用 AND
s 构建查询表达式。所以在循环之后,你终于可以调用.ToList() 最终命中数据库。
更新
和.Select() 不是必需的。
data = data.Where(filter.strFilter + FormatOperator(filter.strOperator) + "@0", filter.strValue);
更新2
哦,再次阅读您的问题后,我知道您需要使用 OR 构建查询。
使用标准库时,这有点困难。如果您不介意引入额外的依赖项,那么可以使用 LinqKit 完成
IQueryable<Product> SearchProducts (params string[] keywords)
{
var predicate = PredicateBuilder.False<Product>();
foreach (string keyword in keywords)
{
string temp = keyword;
predicate = predicate.Or (p => p.Description.Contains (temp));
}
return dataContext.Products.Where (predicate);
}
虽然我不确定它与动态 Linq 的配合效果如何。
否则,您必须手工制作表达式,最终可能如下所示:
public static class IQueryableExtensions
{
public static IQueryable<T> WhereIn<T, TValue>(
this IQueryable<T> source,
Expression<Func<T, TValue>> propertySelector,
IEnumerable<TValue> values)
{
return source.Where(GetWhereInExpression(propertySelector, values));
}
private static Expression<Func<T, bool>> GetWhereInExpression<T, TValue>(
Expression<Func<T, TValue>> propertySelector, IEnumerable<TValue> values)
{
if (!values.Any())
return c => false;
ParameterExpression p = propertySelector.Parameters.Single();
// You'll have to adjust this:
var equals = values.Select(value => (Expression)Expression.Equal(
propertySelector.Body, Expression.Constant(value, typeof(TValue))));
var body = equals.Aggregate<Expression>(
(accumulate, equal) => Expression.Or(accumulate, equal));
return Expression.Lambda<Func<T, bool>>(body, p);
}
}