我有一个在页面上显示用户列表的应用程序。客户端可以选择过滤用户。在我的存储库中,我有一个Linq查询,该查询返回User的IQueryable。我将筛选器和分页应用于IQueryable结果,并调用.ToList()。我无法使日期过滤正常工作。如果我在日期搜索中包含“ /”,它将不会返回任何内容。例如,我有一个DOB 07/10/2000的患者。当我键入“ 07”时,它将返回患者,但如果键入“ 07 /”,则不返回患者。我可以对以下查询进行哪些更改,而无需在分页前调用.ToList()来使日期过滤正常工作?
IQueryable<User> users = _db.Users.Where(x => x.UserID == userID && x.Active == true);
if (!string.IsNullOrWhiteSpace(param.filterValue))
{
users = users.Where(x => x.firstName.ToLower().Contains(param.filterValue.ToLower())
|| x.lastName.ToLower().Contains(param.filterValue.ToLower())
|| x.dateOfBirth.ToString().Contains(param.filterValue.ToLower())
);
}
已更新2018年8月17日
dateOfBirth是一个DateTime字段。但是,时间却被忽略了。 param.filterValue是下面显示的Parameters类的实例。它包含在搜索框中输入的值。
public class Parameters
{
public int MAX_PAGE_SIZE {
get {
return 100;
}
}
public string filterValue { get; set; }
public int PageIndex { get; set; }
public int PageSize { get; set; }
}
此外,我尝试了此更改。
x.dateOfBirth.ToString("MM/dd/yyyy").Contains(param.filterValue.ToLower())
它引发异常
LINQ to Entities does not recognize the method 'System.String ToString(System.String)' method, and this method cannot be translated into a store expression.
答案 0 :(得分:0)
之所以会出现此异常,是因为EF Core不能将所有c#函数都转换为数据库级函数。
在EFCore中的db列上不允许使用c#的ToLower()。
“用户是用户的IQueryable。如果我在用户上调用.ToList()并在之后应用过滤器,则它可以正常工作。仅当将其应用于IQueryable用户时,它才不起作用”->由于IQueryable。在使用IQueryable的情况下,将过滤器应用于数据库本身,然后再将记录提取到内存中。在IQueryable上调用ToList(),获取内存中的记录,并成为IEnumerable。
如果您将Microsoft SQL Server用于数据库用途,则可以签出Microsoft定义的以下DbFunctions。
对于名字和姓氏过滤器,您可以这样写
users.Where(x => EF.Functions.Contains(x.firstName, param.filterValue.ToLower())
|| EF.Functions.Contains(x.lastName), param.filterValue.ToLower())
);
关于x.dateOfBirth,不确定为什么要将Datetime字段转换为字符串,然后调用Contains函数。如果数据库中已经是NVarchar或Varchar数据类型,则可以与firstName / lastName
相同EF.Functions.Contains(x.dateOfBirth, param.filterValue.ToLower())
或者如果是日期时间,则可以将param.filterValue解析为Datetime并使用上述给定URL中的任何EF.DateDiff()函数。
您还可以定义自己的自定义DbFunction,请参考此post
答案 1 :(得分:-1)
如下更改代码:
if (!String.IsNullOrWhiteSpace(SearchString))
{
users = users.Where(s => s.LastName.ToLower().Contains(SearchString.ToLower())
|| s.FirstName.ToLower().Contains(SearchString.ToLower())
|| s.DateOfBirth.ToString("MM/dd/yyyy").Contains(SearchString.ToLower()));
}
将当前DateTime对象的值转换为其等效的短日期字符串表示形式。
更新:
s.DateOfBirth.ToString("MM/dd/yyyy")
支持EntityFrameworkCore
,似乎您正在使用EntityFramework
之后仅支持s.DateOfBirth.ToString()
的{{1}}。在EF 6.1
之前,它甚至不支持EF 6.1
。
要解决此问题,请尝试将s.DateOfBirth.ToString
更改为IQueryable
。
AsEnumerable