问题
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?
回答1:
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());
回答2:
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();
来源:https://stackoverflow.com/questions/65193835/using-linq-to-find-if-a-text-field-contains-any-string-in-a-list