我有一个像这样的模型:
用户:
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)
这部分的缘故,但我目前不考虑任何其他选择。
答案 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));