简体   繁体   English

EF Core:where 子句检查是否至少一个字符串列包含数组中的所有值

[英]EF Core: where clause to check if at least one string column contains all values in an array

To implement a basic search function on an entity, I'd like to check that at least one of multiple fields contain all the provided search terms.要在实体上实现基本搜索功能,我想检查多个字段中是否至少有一个包含所有提供的搜索词。

To illustrate, let's imagine my entity is a Furniture with two string fields named Name and Description , and I have the following entries in my database:为了说明这一点,让我们假设我的实体是一个具有两个名为NameDescription字符串字段的Furniture ,并且我的数据库中有以下条目:

    ID | Name           |  Description
    ---|----------------|------------
    1  | Black chair 1  | Black chair
->  2  | Red chair 1    | Crimson chair
->  3  | Red chair 2    | Dark red chair
->  4  | Black chair 2  | Black straight back chair, red cushion
    5  | Blue sofa      | Blue sofa
    6  | Red sofa       | Red sofa

and that I want to retrieve all the entities where any of the fields contain the two words red and chair (so here, 2, 3, and 4).并且我想检索其中任何字段包含两个词redchair所有实体(所以这里是 2、3 和 4)。

I can write this:我可以这样写:

var search = new[] { "red", "chair" };
var filtered = _db.Furnitures.AsNoTracking().Where(f => {
       search.All(s => f.Name.ToLower().Contains(s)) 
    || search.All(s => f.Description.ToLower().Contains(s))
});

but EF Core warns me that this can't be translated to SQL, and that it will be evaluated locally.但是 EF Core 警告我这不能转换为 SQL,它将在本地进行评估。

Is there any way can I write this query so that it's evaluated in SQL?有什么办法可以编写此查询,以便在 SQL 中对其进行评估?

Note : this is a simplified example of the issue I'm facing, and the model is obviously ridiculous, so please don't suggest a change in my entities :)注意:这是我面临的问题的一个简化示例,该模型显然很荒谬,所以请不要建议更改我的实体:)

You can create a handful of criteria as expressions outside of your LINQ statement, and then apply them all to your query individually:您可以在 LINQ 语句之外创建一些条件作为表达式,然后将它们全部应用于您的查询:

    var search = new[] { "red", "chair" };
    var criteria = search.Select(s => (Expression<Func<Furniture, bool>>)(f => f.Name.ToLower().Contains(s) || f.Description.ToLower().Contains(s)))
        .ToList();
    var query = criteria.Aggregate(
        _db.Furnitures.AsNoTracking().AsQueryable(),
        (query, criterion) => query.Where(criterion));

For more advanced situations (eg OR instead of AND ), you may need to do some expression tree manipulation, as I describe here .对于更高级的情况(例如OR而不是AND ),您可能需要进行一些表达式树操作,正如我在此处所述。

    var search = new[] { "red", "chair" };
    var criteria = search.Select(s => (Expression<Func<Furniture, bool>>)(f => f.Name.ToLower().Contains(s) || f.Description.ToLower().Contains(s)))
        .ToList();
    var query = _db.Furnitures.AsNoTracking().
        .Where(Join(Expression.And, criteria));

Is there any way can I write this query so that it's evaluated in SQL?有什么办法可以编写此查询,以便在 SQL 中对其进行评估?

The best option would be to use a raw query that you write yourself.最好的选择是使用您自己编写的原始查询

There is nothing faster or more flexible than using raw queries to select data from a SQL database.没有什么比使用原始查询从 SQL 数据库中选择数据更快或更灵活了。 It gives you exactly what you want and avoids the overhead of processing and translating expressions at runtime.它准确地为您提供所需的内容,并避免在运行时处理和翻译表达式的开销。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM