[英]calculateAge (or year) from LINQ Query DateTime field using C# for comparision (Age From)
请参阅calculateAge在LINQ查询中将出生日期转换为以年为单位的当前年龄(它适用于其他键,例如:EyeColor,但年龄转换失败),我想与存储在数组中的值进行比较。 我尝试将值存储在链接上方,“ case“ AgeTo”:“正下方的DateTime临时变量中,但我无法采用x.profile.BirthDate值,因为仅在LINQ Query中允许使用它。 看起来LINQ查询在构建期间没有给出错误,但是,它无法
错误:
LINQ to Entities无法识别方法'Int32calculateAge(System.DateTime)'方法,并且该方法无法转换为商店表达式。
任何帮助如何处理?
代码和calculateAge方法:
if (searchList.Count > 0)
{
foreach (KeyValuePair<String, String> kvp in searchList)
{
switch (kvp.Key)
{
case "AgeFrom":
photosquery = photosquery.Where(x => calculateAge(Convert.ToDateTime(x.profile.BirthDate)) >= Convert.ToInt32(kvp.Value));
break;
case "AgeTo":
photosquery = photosquery.Where(x => calculateAge(Convert.ToDateTime(x.profile.BirthDate)) <= Convert.ToInt32(kvp.Value));
break;
case "EyeColor":
photosquery = photosquery.Where(x => x.physical.EyesColor.Contains(kvp.Value));
break;
}
}
}
//My code for calculateAge:
public static int calculateAge(DateTime birthDay)
{
int years = DateTime.Now.Year - birthDay.Year;
if ((birthDay.Month > DateTime.Now.Month) || (birthDay.Month == DateTime.Now.Month && birthDay.Day > DateTime.Now.Day))
years--;
return years;
}
出现此错误的原因是, Where
可查询的Entity上调用了Where-子句,并且它不知道如何将C#代码转换为数据库语言的等效代码。
如果您能够将该函数的内部重写为不具有基于.NET的变量存储或仅引用数据库中可用的CLR函数的东西,则可以内联使用它,就好像您没有该函数一样呼叫:
var now = DateTime.Now;
...
case "AgeFrom":
photosquery = photosquery.Where(x => DbFunctions.DiffYears(x.profile.BirthDate,now) >= Convert.ToInt32(kvp.Value));
break;
如果要使用已有的代码,则需要在过滤之前检索所有数据,通常不建议这样做。 您仍然可以通过在.Where(..)子句之前调用.ToList()来实现此目的。
有一个更简单的解决方案。 与其比较年龄,不如比较日期本身。
case "AgeFrom":
var fromAge = Convert.ToInt32(kvp.Value);
var maxDate = DateTime.Today.AddYears(-fromAge);
photosquery = photosquery.Where(x => x.profile.BirthDate <= maxDate);
break;
case "AgeTo":
var toAge = Convert.ToInt32(kvp.Value);
var minDate = DateTime.Today.AddYears(-toAge-1).AddDays(1);
photosquery = photosquery.Where(x => x.profile.BirthDate >= minDate);
break;
这具有使查询成为可扩展查询的额外好处,因此假设您已在BirthDate
字段上创建了一个索引,则它可以利用索引。
您正在使用IQueryable
,因此无法在实现之前将其与任意C#
代码混合使用。
现在,您有两个选择:
ToList
或ToArray
将所有数据加载到应用程序内存中,然后应用过滤方法 sql
函数(在这种情况下为DATEPART
) 对于第二种方法,您可以编写此查询(在switch
之前):
var newQuery = photosquery.Select(x => new
{
AllQuery = x,
yearsDiff = (x.profile.BirthDate.Month > now.Month) ||
(x.profile.BirthDate.Month == now.Month
&& x.profile.BirthDate.Day > now.Day)
? now.Year - x.profile.BirthDate.Year - 1
: now.Year - x.profile.BirthDate.Year
});
然后,当您输入switch
您可以写:
case "AgeFrom":
photosquery = newQuery
.Where(x => x.yearsDiff >= Convert.ToInt32(kvp.Value))
.Select(x => x.AllQuery );
break;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.