c# - 过滤包含 (%like%) 列表中任何项目的 IQueryable
问题描述
我想在不访问数据库的情况下使用 List 过滤 IQueryable/List。IQueryable 结果应包括包含列表中任何字符串的所有结果,并且列表的长度未指定。
myQueryable = myQueryable.Where(filelist => filelist.Location.Contains(filterList[0]) || filelist.Location.Contains(filterList[1]) || filelist.Location.Contains(filterList[N])...);
我正在使用 ASP.NET Core 3,并将使用 IQueryable 在稍后阶段使用 Entity Framework 访问数据库。
我已经尝试了这两个不起作用的代码,如果我排除我的试用代码(用于过滤属性、位置),我的 IQuery 工作正常。
workOrders = workOrders.Where(filelist => filterList.Contains(filelist.Location)); //Returns only exact match
workOrders = workOrders.Where(filelist => filterList.Any(filter => filelist.Location.ToUpperInvariant().Contains(filter.ToUpperInvariant()))); //Returns error
Expression<Func<Workorder, bool>> predicate = filelist => false; foreach (var filter in filterList) { Expression<Func<Workorder, bool>> orPredicate = filelist => filter.Contains(filelist.Location); var body = Expression.Or(predicate.Body, orPredicate.Body); predicate = Expression.Lambda<Func<Workorder, bool>>(body, predicate.Parameters[0]); } workOrders = workOrders.Where(predicate); //Returns Error
class Workorder //Database Model
{
public string SiteId { get; set; }
public string Location { get; set; }
}
List<string> filterList //List to be used as filter
{
"filterOne",
"filterTwo",
"filterN"
};
我运行的第二个代码给了我一个错误,我什么也得不到。
System.InvalidOperationException:从“VisitLambda”调用时,重写“System.Linq.Expressions.ParameterExpression”类型的节点必须返回相同类型的非空值。或者,覆盖“VisitLambda”并将其更改为不访问此类型的子项。
我运行的第三个代码给了我这个错误,
System.InvalidOperationException:由于对象的当前状态,操作无效。在 Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateWhere(ShapedQueryExpression 源,LambdaExpression 谓词)
解决方案
我绝对没有测试过这个......但我认为如果你假装 EF 事后解析它,你不能用单线来做到这一点。
但是,这样的事情应该没问题:
Expression<Func<WorkOrder, bool>> predicate = filelist => false;
foreach(var filter in filterList) {
Expression<Func<WorkOrder, bool>> orPredicate = filelist => filter.Contains(filelist.Location);
var body = Expression.Or(predicate.Body, orPredicate.Body);
predicate = Expression.Lambda<Func<WorkOrder,bool>>(body, predicate.Parameters[0]);
}
进而:
myQueryable = myQueryable.Where(predicate);
我们基本上只是告诉它:
.Where(filelist => false || filterList[0].Contains(filelist.Location) || filterList[1].Contains(filelist.Location) || ...);
编辑
仍未在 EF 上测试,但至少语法似乎没问题:https ://dotnetfiddle.net/Htr7Zr
推荐阅读
- sql - 使用 case 语句并为每条前 10 条记录设置不同的值
- azure - JMESPath如何汇总数据
- apache-nifi - 如何恢复从文件系统中删除(通过 GetFile)并在 Content Repository 中保存为 FlowFiles 的文件?
- powerbi - 计数的 Power BI 多个条件
- python - pyodbc 连接具有相同命名列的表(“upsert”)
- java - TestNG:使用 Testng XML 文件运行特定的组测试
- google-cloud-platform - 如何为 GCP 项目中的每个人生成 GCP DataPrep 流的全局访问令牌?
- spring-kafka - spring kafka 是否支持使用 spring boot 2.3 优雅关闭?
- postgresql - 如何从 pod 内部更改 Postgres 数据库用户名?
- tensorflow - 如何在tensorflow js中使用预测