我正在开发一个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无法识别方法' System.DateTime ToLocalTime()'方法,这个方法无法翻译成一个 商店表达。
我需要将l.Date
转换为本地时间,然后与search
我该怎么做?
答案 0 :(得分:1)
每个人都已经指出了明显的错误,但想想你要求代码做什么。遍历每条记录,对其进行操作以转换为本地时间,将其转换为字符串,然后对字符串进行搜索。如果您在数据库中获得任何重要记录,这听起来像是一个糟糕的性能计划。
正如Rush Frisby指出的那样,如果你沿着这条路走下去,那么你真的需要考虑一个存储过程。
我认为您问题的真正答案是您需要更好的搜索逻辑。如果您可以预先定义搜索是否是查询之前的日期时间,那么您甚至可以在执行数据库之前实现DT偏移并按实际时间搜索,更不用说避免在名称上进行文本搜索。否则,如果它只是一个自由文本搜索,那么你可以点击命名列。
我可能会被投票,因为这并没有真正回答直接问题,但我认为你问题的最佳答案是改变整体搜索逻辑架构。
答案 1 :(得分:0)
您无法在表达式内调用ToLocalTime方法,因为EF不知道如何将其转换为SQL语句。如果出现此类异常,请检查SqlFunctions并尝试找到适合您目的的方法。
还考虑在当地时间存储该日期。或者不是与搜索进行比较,而是将其与var dateSearchCriteroa = searchCriteria.ToNotLocal()
进行比较。答案 2 :(得分:0)
LINQ to Entities不会将大多数.NET Date方法(包括您使用的转换和日期时间操作)转换为SQL,因为SQL中不存在等效的这些方法。
或者您可以将搜索过滤器转换为来自数据库的数据时间格式,而不是尝试将其转换为LocalTime。
答案 3 :(得分:0)
1)规范化Date
列数据,使Logs
中的所有行都属于同一时区。最好的选择,因为您没有在查询中进行转换,这将使查询更快,加上其他原因,如使报告更容易阅读。
2)使用sproc或参数化查询,使用SQL函数Date
TODATETIMEOFFSET(<date>,<offset>)
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会将Date转换为您的服务器设置的本地时间,而不是用户查看网页的本地时间。如果你想这样做,那么你需要从请求标题或通过javascript获取他们的时区并将其与请求一起传递,然后使用该值来格式化Date,然后再将其传递回View - 或者只是进行转换客户端使用javascript。