【问题标题】:using linq to find if a text field contains any string in a list使用 linq 查找文本字段是否包含列表中的任何字符串
【发布时间】:2021-03-19 11:22:46
【问题描述】:

我在 asp.net core v3.1 中运行它

我的问题类似于这个问题:
How to use Linq to check if a list of strings contains any string in a list

与第一个答案相关的具体问题

filterTags = ["abc", "cd", "efg"]
var results = db.People
                .Where(p => filterTags.Any(tag => p.Tags.Contains(tag)));

所以基本上是说
给我所有人数据库的结果
谁的标签字段包含任何 filterTags
其中标签 = 由一堆空格分隔的标签填充的大文本字段

这看起来很简单(尤其是因为之前已经写过)
但我得到一个错误返回

System.InvalidOperationException:LINQ 表达式 'DbSet .Where(p => __filterTags_0 .Any(tag => p.Tags.Contains(tag)))' 无法翻译。以可翻译的形式重写查询,或通过插入对 AsEnumerable()、AsAsyncEnumerable()、ToList() 或 ToListAsync() 的调用显式切换到客户端评估

有谁知道这意味着什么或我做错了什么?

【问题讨论】:

  • @TAHASULTANTEMURI - intersect 用于两个列表,而我专门寻找一个列表中的任何内容以显示在长字符串中的某处
  • 我指的是下一个,你应该 var People= _db.People.Where(p => p.Tagse.Split(',').ToList().Any(x => filterTags.Contains(x));
  • 执行此代码:List<string> filterTags = new List<string> { "abc", "cd", "efg" }; var results = db.People.ToList().Where(p => filterTags.Any(tag => p.Tags.Contains(tag))).ToList()
  • 银秋:您的解决方案会将所有数千人从数据库转移到您的本地进程,然后再丢弃其中的大部分。

标签: linq asp.net-core contains any


【解决方案1】:

这对于纯 EF LINQ 是不可能的。您必须创建帮助器来转换表达式树中的搜索列表。

public static class QueryExtensions
{
    private static MethodInfo _containsMethodInfo = typeof(string).GetMethod("Contains")!;

    public static IQueryable<T> FilterUsingContains<T>(this IQueryable<T> query, Expression<Func<T, string>> prop, IList<string> items)
    {
        if (items.Count == 0)
            return query.Where(e => 1 == 2);

        var param = prop.Parameters[0];

        var predicate = items.Select(i =>
                (Expression)Expression.Call(prop.Body, _containsMethodInfo, Expression.Constant(i, typeof(string))))
            .Aggregate(Expression.OrElse);

        var lambda = Expression.Lambda<Func<T, bool>>(predicate, param);

        return query.Where(lambda);
    }
}

然后你可以在你的查询中使用这个扩展

filterTags = ["abc", "cd", "efg"]
var results = db.People
    .Where(p => p.Tags.AsQueryable().FilterUsingContains(t => t, filterTags).Any());

【讨论】:

    【解决方案2】:

    这里有一个解决方法:

    using System.Linq; 
    
    string[] filterTags = {"abc", "cd", "efg"};
    var results = db.People.Where(p => filterTags.Contains(p.Tags)).ToList();
    

    【讨论】:

    • 您的代码无法编译。 p.Tags 显然是 List&lt;string&gt;。您将其视为string
    • @Enigmativity 你犯了一个错误。只需准确地看一下这个问题。它说“标签 = 由一堆空格分隔的标签填充的大文本字段”,所以标签是一个字符串。
    • IEnumerable&lt;string&gt;.Contains 没有需要 lambda 的重载。您的代码仍然无法编译。
    • @Enigmativity 再次我应该说你没有完全阅读这个问题。问题已经提到在变通方法中必须考虑使用 Linq。所以使用 Linq 字符串数组可以应用 Contains 方法。
    • 也许您应该测试您的代码 - IEnumerable&lt;string&gt;.Contains 方法没有采用 lambda 的重载。您的代码无法编译。
    猜你喜欢
    • 2023-03-14
    • 2014-07-08
    • 2016-01-27
    • 1970-01-01
    • 2021-11-26
    • 2021-12-11
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    相关资源
    最近更新 更多