使用EF将内容搜索到两列

时间:2019-12-09 15:25:50

标签: c# entity-framework-core

我有一个像这样的模型:

用户:

string FirstName {get; set;}
string LastName {get; set; }

我正在做一个搜索,我想在其中搜索发送的模式是名字的一部分,姓氏的一部分还是整个连接的一部分。

所以我基本上已经做到了:

entities = entities.Where(user => user.Contains(text));

使用执行以下操作的用户扩展方法:

    public static bool Contains(this User user, string filter)
    {
        return user.FirstName.Contains(filter) ||
            user.LastName.Contains(filter) ||
            (user.FirstName + "  " + user.LastName).Contains(filter);
    }

但是我总是收到以下错误:

(__ filterText_1))'无法翻译,将在本地进行评估。'。通过将事件ID'RelationalEventId.QueryClientEvaluationWarning'传递到'DbContext.OnConfiguring'或'AddDbContext'中的'ConfigureWarnings'方法,可以抑制或记录此异常。

我认为这是因为(user.FirstName + " " + user.LastName)这部分的缘故,但我目前不考虑任何其他选择。

3 个答案:

答案 0 :(得分:1)

问题是您的扩展方法无法转换为SQL。实体框架使用表达式树来将lambda转换为SQL。

旧答案

相反,您的扩展方法可以返回Expression,如下所示:

public static Expression<Func<User, bool>> Contains(this User user, string filter)
{
    return user.FirstName.Contains(filter) ||
            user.LastName.Contains(filter) ||
            (user.FirstName + "  " + user.LastName).Contains(filter);
}

然后您可以在Where中使用它。

更新答案

您可以在类中创建一个私有方法来构建过滤器表达式,而不是扩展方法,然后将其传递给Where

private Expression<Func<User, bool>> GetFilterExpression(string filter)
{
    return user => user.FirstName.Contains(filter) ||
            user.LastName.Contains(filter) ||
            (user.FirstName + "  " + user.LastName).Contains(filter);
}

然后将该方法传递给Where

entities = entities.Where(GetFilterExpression(text));

我认为您将无法使用扩展方法。

答案 1 :(得分:0)

请尝试使用EF函数String.Contains,而不要使用Like。您可以将Contains查询更改为以下内容:

public static bool Contains(this User user, string filter)
{
    return EF.Functions.Like(filter, $"%{user.FirstName}%") ||
        EF.Functions.Like(filter, $"%{user.LastName}%") ||
        EF.Functions.Like(filter, $"%{user.FirstName} {user.LastName}%");
}

尽管,如果您不需要同时搜索开头和结尾,最好不要使用全文本搜索,而只限于开头。

答案 2 :(得分:0)

我只是不必使用扩展方法,而使用

user.FirstName.Contains(filter) ||
            user.LastName.Contains(filter) ||
            (user.FirstName + "  " + user.LastName).Contains(filter);

直接在哪里而不是在扩展方法上使用

entities = entities.Where(user => user.FirstName.Contains(text) ||
                user.LastName.Contains(text) ||
                (user.FirstName + "  " + user.LastName).Contains(text));