我想使用波斯语日历过滤我的查询。
我的原始查询:
var getNews =
from gn
in db.NewsTables
where gn.Show
select gn;
波斯日历对象:
PersianCalendar pc = new PersianCalendar();
并过滤原始查询,如下所示:
getNews = getNews.Where(nm => pc.GetMonth(nm.InsertionDate) == 9 && pc.GetYear(nm.InsertionDate) == pc.GetYear(DateTime.Now));
和例外:
base {System.SystemException} = {" LINQ to Entities无法识别 方法' Int32 GetMonth(System.DateTime)'方法和这种方法 无法翻译成商店表达。"}
任何人都有任何想法?
答案 0 :(得分:1)
Linq to Entities
仅支持canonical functions查询。所以这是不幸的是不支持。
如果数据集不是太大,您可以完全检索它(例如,使用ToList()
),然后使用Linq to Objects
过滤它,只需考虑必须检索整个数据集(如果数据库服务器不是本地的,则传输),这可能会对内存和性能产生影响。
或者,如果数据库记录存储在格里高利日期(如评论中所述),您可以事先进行转换......遵循您的代码:
var gregorianDate = new DateTime(DateTime.Now.Year, 9, 1, new PersianCalendar());
getNews = getNews.Where(nm => nm.InsertionDate.Month == gregorianDate.Month
&& nm.InsertionDate.Year == gregorianDate.Year);
答案 1 :(得分:1)
有两种不同的方法可以阅读这个问题:
第一部分可以通过将查询转换为月末的开始和结束之间的范围查询来修复:
var startDate=DateTime.Today.AddDays(1-DateTime.Today.Day);
var endDate=startDate.AddMonths(1);
var getNews = from gn in db.NewsTables
where gn.Show
&& gn.InsertionDate >=startDate
&& gn.InsertionDate <endDate
select gn;
DateTime.Today
和DateTime.Now
总是返回格里高利日期,所以我假设搜索日期是由用户输入的,或者通过其他方式输入为波斯日期,数据存储在公历中。
在这种情况下,您可以使用PersianCalendar方法计算范围。 DateTime值始终在公历中,这意味着您不必须做任何事情才能转换为Gregorian:
var calendar = new PersianCalendar();
var startDate= calendar.AddDays(searchDate,1- calendar.GetDayOfMonth(searchDate));
var endDate=calendar.AddMonths(startDate,1);
var getNews = from gn in db.NewsTables
where gn.Show
&& gn.InsertionDate >=startDate
&& gn.InsertionDate <endDate
select gn;
我建议您使用像Jon Skeet的Noda Time这样的图书馆,它知道日历并且没有假设所有当地时间都是格里高利
答案 2 :(得分:-1)
容易(但可能很糟糕)的答案是:
getNews = getNews.ToList();
getNews = getNews.Where(nm => pc.GetMonth(nm.InsertionDate) == 9 && pc.GetYear(nm.InsertionDate) == pc.GetYear(DateTime.Now));
正如Jcl所说,错误的原因是LINQ to Entities只支持有限数量的函数(可以转换为底层提供程序可以支持的表达式)。您的pc.GetMonth
功能不是它理解的功能。
通过执行ToList()
,您强制查询在服务器上执行并返回结果。现在getNews
只是本地内存中的一个集合,任何进一步的LINQ操作都将使用LINQ to Objects完成,它没有上述限制。
*如果在过滤之前数据集很小,这只是一个很好的解决方案,因为getNews
查询的整个结果集必须返回并存储在内存中才能过滤。如果它是20行,我不会担心它。如果它是2000,你应该找到一种重构的方法。
答案 3 :(得分:-1)
实体将您的代码转换为sql语言,在这种情况下,它无法将您的函数GetMonth转换为SQL。快速解决方法是
var getNews =
(from gn
in db.NewsTables
where gn.Show
select gn).ToList();
但这意味着您将从内存中的数据库中获取所有记录,并在选择后应用过滤器。
如果您向我们展示您的功能代码,我们将能够帮助您直接在数据库中进行过滤。