我正在开发一个MVC网站。 在其中一种视图中,我需要使用:
return View(db.Logs
.OrderByDescending(l => l.Date)
.Where(l => ((DateTime)l.Date).ToLocalTime().ToString().Contains(search)
|| l.Name.Contains(search))
.ToList()
.ToPagedList(pageNumber, pageSize));
但是我得到这个错误:
LINQ to Entities does not recognize the method 'System.DateTime
ToLocalTime()' method, and this method cannot be translated into a
store expression.
我需要将l.Date转换为LocalTime,然后与search进行比较
我该怎么做?
因为错误说ToLocaltime()在Linq中不支持实体。您需要在linq to Entities操作之后执行该转换
您是否尝试过((((DateTime)l.Date).ToLocalTime()。ToString())。Contains(search)?
您无法在Linq上使用强制类型转换,请尝试在使用属性类型相同的操作之前声明一个变量
而不是尝试将表行值转换为LocalTime,而是尝试将搜索条件转换为UTC日期时间。这可能相似
@ user9405863我该怎么办?
您应该将日志具体化为一个列表:varorderedLogs = db.Logs.OrderByDescending(l => l.Date).ToList()。然后使用LINQ筛选orderedLogs。效率较低,但应该可以。
@OleAlbers我刚刚尝试过,不起作用。
@Samuel我该怎么办?我需要l.Date,它在lambda表达式内。
@AlexandruPopa这不是问题...
@Jmyebenes,你尝试过吗?我很确定它应该工作。您不能在实体上使用.ToLocalTime(),因为它无法将其转换为SQL代码,但它应在内存列表中工作。
您可以更改它以返回View(db.Logs.OrderByDescending(l => l.Date).ToArray().Where(l =>((DateTime)l.Date).ToLocalTime()。ToString()。Contains(搜索)|| l.Name.Contains(search))。ToList()。ToPagedList(pageNumber,pageSize));但仅用于测试目的。这个东西从服务器获取所有数据并在内存中进行过滤
您实际上想做什么?将日期转换为字符串(甚至不指定格式),然后检查它们的子字符串似乎是实现日期搜索的一种奇异方法。
完美工作的@EugeneGorbovoy!谢谢!
@JoeFarrell这是因为我有搜索框,我可以搜索名称的一部分或日期的一部分,或者您想要的任何内容,因此我需要转换为不带格式的字符串,因为它可以是名称,而不是日期。
每个人都已经指出了明显的错误,但请考虑您要您的代码做什么。遍历每条记录,对其进行操作以将其转换为本地时间,将其转换为字符串,然后对字符串进行搜索。如果您在数据库中获得任何重要记录,这听起来像是一个糟糕的性能计划。
正如Rush Frisby指出的那样,如果您走了这条道路,那么您确实需要考虑存储过程。
我认为对您的问题的真正答案是,您总体上需要更好的搜索逻辑。如果您可以预定义搜索是否是查询之前的日期时间,那么您甚至可以在访问数据库并按实际时间进行搜索之前就已经实现了DT偏移,更不用说避免按名称搜索文本了。否则,如果这只是一个自由文本搜索,那么您可以按一下名称列。
我可能会被否决,因为这并不能真正回答直接问题,但我认为对您问题的最佳答案是改变整体搜索逻辑体系结构。
1)标准化您的Date列数据,以使Logs中的所有行都处于相同的时区。最佳选择,因为您没有在查询中进行转换,这会使查询速度更快,还有其他原因,例如使报告更易于阅读。
2)使用一个存储过程或参数化查询,在其中使用SQL函数TODATETIMEOFFSET(,)转换Date
3)如果要在查询后对其进行转换,则应在查询上调用ToList(),以便它拉回数据,然后将日期转换为本地时区:
var data = db.Logs.OrderByDescending(l => l.Date)
.Where(l => ((DateTime)l.Date).ToString().Contains(search)
|| l.Name.Contains(search))
.Skip((pageNumber-1)*pageSize).Take(pageSize)
.ToList(); //ToList() causes the query to execute
//now you can convert the Date
foreach (var item in data)
{
item.Date = item.Date.ToLocalTime();
}
return View(data);
您还应该在查询中使用Skip和Take而不是ToPagedList,这样就不会撤回所有数据。
4)在视图(不是控制器)中,可以在显示变量时调用ToLocalTime(假设Razor)@Model.Date.ToLocalTime()
您必须记住,尽管ToLocalTime会将日期转换为服务器设置的本地时间,而不是将用户查看网页的本地时间转换为本地时间。如果要执行此操作,则需要从请求标头或通过javascript获取其时区,然后将其与请求一起传递,然后使用该值设置Date的格式,然后将其传递回View-或仅执行该转换客户端使用javascript。
我想将utc日期保存在sql中,但以本地日期格式显示此日期,因此第一点被取消了笛卡尔。 第二个选项如何工作?
以本地格式显示日期应该在前端而不是在数据库查询中处理。
LINQ to Entities不会将大多数.NET Date方法(包括您使用的转换和日期时间操作)转换为SQL,因为SQL中不存在这些方法的等效项。
或者,您可以将搜索过滤器转换为来自数据库的datatime格式,而不是尝试将其转换为LocalTime。
您不能在表达式内调用ToLocalTime方法,因为EF不知道如何将其转换为SQL语句。当您收到此类异常时,请检查SqlFunctions并尝试查找适合您目的的任何方法。
还可以考虑将日期存储在当地时间。或者,而不是比较搜索,将其与var dateSearchCriteroa = searchCriteria.ToNotLocal()之类的东西进行比较