LINQ to Entities无法识别DateTime.ToLocalTime()方法

时间:2018-04-18 14:37:57

标签: c# asp.net-mvc linq

我正在开发一个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

进行比较

我该怎么做?

4 个答案:

答案 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);

您还应该在查询中使用SkipTake而不是ToPagedList,这样您就不会撤回所有数据。

4)在您的视图(不是控制器)中,您可以在显示变量时调用ToLocalTime ...(假设Razor)@Model.Date.ToLocalTime()

您必须记住ToLocalTime会将Date转换为您的服务器设置的本地时间,而不是用户查看网页的本地时间。如果你想这样做,那么你需要从请求标题或通过javascript获取他们的时区并将其与请求一起传递,然后使用该值来格式化Date,然后再将其传递回View - 或者只是进行转换客户端使用javascript。