【问题标题】:EF Core complex WhereEF Core 复杂在哪里
【发布时间】:2018-10-08 20:55:39
【问题描述】:

我有一个使用 EF Core 的 MVC 项目。在我的控制器中,我通过 url 接收参数,其中之一是 searchQuery 。我有一张这样格式的客户表:

id | empId | empName | personId | personFirstName | personLastName

请注意,客户要么是雇主,要么是个人,而不是两者。 (相应的字段将为 NULL)。这是我正在使用的查询:

collectionBeforePaging = _context.Customers
    .Where(a => (a.Employer == null ? (a.Person.FirstName.Contains(searchQueryForWhereClause) ||
                                       a.Person.LastName.Contains(searchQueryForWhereClause) ||
                                       a.PersonId.ToString().Contains(searchQueryForWhereClause))
                                    : (a.Employer.Name.Contains(searchQueryForWhereClause) ||
                                       a.EmployerId.ToString().Contains(searchQueryForWhereClause))));

这项工作,虽然不是我想要的方式。如果用户搜索“Jhon Pots”,并且客户是人,那么它将检查名字是否包含“Jhon Pots”或姓氏是否包含,而不是检查名字是否包含“Jhon”并且姓氏是否包含“锅”。

我可以连接 firstNamelastName ,但它必须是完全匹配的(即它不会匹配名为“Jhon S. Pots”的客户)

我还考虑过使用Split 方法分解searchQuery,但我不知道如何将它与EF Where 子句正确结合..(我不能对每个字符串使用foreach 循环和过滤器,因为它将按每个字符串过滤我的结果,而不是使用OR 逻辑运算符)

有人知道我怎样才能做到这一点吗?

【问题讨论】:

    标签: c# asp.net-core entity-framework-core


    【解决方案1】:

    要执行类似 db 的比较,您可以使用 EF.Functions.Like() 方法。

    以空格分隔搜索词,迭代搜索词并在执行前将where子句添加到查询中:

    string[] searchTerms = searchQueryForWhereClause.Split(' ');
    
    var query = _context.Customers.AsQueryable();
    foreach (string searchTerm in searchTerms)
    {
        query = query.Where(x => EF.Functions.Like(x.FirstName, $"%{searchTerm}%"
            || EF.Functions.Like(x.LastName, $"%{searchTerm}%"
            || EF.Functions.Like(x.PersonId, $"%{searchTerm}%"
            || EF.Functions.Like(x.Employer.Name, $"%{searchTerm}%"
            || EF.Functions.Like(x.EmployerId, $"%{searchTerm}%");
    }
    

    【讨论】:

    • 谢谢!因为他们在 ef core 5 中打破了旧的/新的做法,所以很烦人,又名 files = files.Where(x => searchTerms.Any(y => x.OriginalFilename.Contains(y))); 这样的东西在 ef 5 中不起作用,以前可以工作。
    【解决方案2】:

    你需要先拆分你的字符串,然后根据结果数组中的任何项是否匹配每个字段来查询:

    var keywords = searchQuery.Split(' ');
    

    然后:

    collectionBeforePaging = _context.Customers
        .Where(a => a.Employer == null
            ? keywords.Any(k => 
                a.Person.FirstName.Contains(k) ||
                a.Person.LastName.Contains(k) ||
                a.PersonId.ToString().Contains(k))
             : keywords.Any(k =>
                a.Employer.Name.Contains(k) ||
                a.EmployerId.ToString().Contains(k)));
    

    【讨论】:

    • 虽然由于性能偏好我使用了不同的方法,但这正是我想要的,所以谢谢!
    【解决方案3】:

    假设您的客户表具有唯一 ID。对搜索字符串执行拆分,对于每个拆分只返回一个实际客户 ID 的列表。将 id 一起添加到一个列表中,然后使用该 id 列表来获取匹配的客户

    【讨论】:

    • 那是我试图避免的......代码变得太乱了:\
    猜你喜欢
    • 2018-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多