0

im running this in asp.net core v3.1

my question is similar to this question:
How to use Linq to check if a list of strings contains any string in a list

with the specific question relating to the first answer such that

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

so basically saying
give me results from the db of all People
who's Tags field contains any of the filterTags
where Tags = a big text field populated by a bunch of space-delimited tags

This seems straightforward (esp since this has been written before)
but i get an error back

System.InvalidOperationException: The LINQ expression 'DbSet .Where(p => __filterTags_0 .Any(tag => p.Tags.Contains(tag)))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync()

does anyone know what this means or what im doing wrong?

5
  • did you check this ? stackoverflow.com/questions/10667675/… Commented Dec 8, 2020 at 6:00
  • @TAHASULTANTEMURI - intersect is used for two lists while im specifically looking for anything in one list to show up somewhere in a long string Commented Dec 8, 2020 at 6:06
  • I m refering to the next one , you should var People= _db.People.Where(p => p.Tagse.Split(',').ToList().Any(x => filterTags.Contains(x)); Commented Dec 8, 2020 at 6:08
  • Do this code : List<string> filterTags = new List<string> { "abc", "cd", "efg" }; var results = db.People.ToList().Where(p => filterTags.Any(tag => p.Tags.Contains(tag))).ToList() Commented Dec 8, 2020 at 6:15
  • 1
    Yinqiu: your solution would transfer all thousands of People from the Database to your local process before throwing away most of them. Commented Dec 8, 2020 at 7:24

2 Answers 2

2

This is not possible with pure EF LINQ. You have to create helper which transforms your search list in Expression Tree.

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);
    }
}

Then you can use this extension in your queries

filterTags = ["abc", "cd", "efg"]
var results = db.People
    .Where(p => p.Tags.AsQueryable().FilterUsingContains(t => t, filterTags).Any());
Sign up to request clarification or add additional context in comments.

1 Comment

Great! Just a little correction in _constainsMethodInfo (.Net Core 5.0): private static MethodInfo containsMethod = typeof (string).GetMethod("Contains", new Type[]{typeof (string)});
-1

Here is a workaround for you:

using System.Linq; 

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

8 Comments

Your code wouldn't compile. p.Tags is clearly a List<string>. You're treating it like it is a string.
@Enigmativity You made a mistake. Just take a precise look at the question. It says "Tags = a big text field populated by a bunch of space-delimited tags", so Tags is a string.
There's no overload of IEnumerable<string>.Contains that takes a lambda. You code still does not compile.
@Enigmativity Again I should say that you don't read the question exactly. The question has mentioned that the use of Linq must be considered in the workaround. So using Linq the string array can apply the Contains method.
Perhaps you should test your code - the IEnumerable<string>.Contains method does not have an overload that takes a lambda. Your code would not compile.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.