LINQ to Entities异常不支持指定的类型成员'Date'


105

在执行以下语句时出现异常。

 DateTime result;
 if (!DateTime.TryParse(rule.data, out result))
     return jobdescriptions;
 if (result < new DateTime(1754, 1, 1)) // sql can't handle dates before 1-1-1753
     return jobdescriptions;
 return jobdescriptions.Where(j => j.JobDeadline.Date == Convert.ToDateTime(rule.data).Date );

例外

The specified type member 'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.

我知道例外的含义,但我不知道如何摆脱它。有什么帮助吗?


这是EF6及更低版本。EF核心支持.Date
Gert Arnold

Answers:


102

LINQ to Entities无法将大多数.NET Date方法(包括您使用的转换)转换为SQL,因为没有等效的SQL。

解决方案是在LINQ语句外部使用Date方法,然后传递一个值。看起来好像Convert.ToDateTime(rule.data).Date导致了错误。

在DateTime属性上调用Date也不能转换为SQL,因此一种解决方法是比较.Year .Month和.Day属性,因为它们只是整数,因此可以转换为LINQ。

var ruleDate = Convert.ToDateTime(rule.data).Date;
return jobdescriptions.Where(j => j.Deadline.Year == ruleDate.Year 
                       && j.Deadline.Month == ruleDate.Month 
                       && j.Deadline.Day == ruleDate.Day);

6
那么j => j.JobDeadline.Date呢?
星云

1
Date是JobDeadline上的财产吗?这本身不应导致错误-可能是命名冲突(但不能确定此错误)。如果该行仍然引起错误,则将其重命名为DeadlineDate或类似名称。
2012年

1
日期是JobDeadline上的属性。JobDeadline是我要提取日期的DateTime类型。
星云

然后,要在LINQ中工作,您只需要比较JobDeadline属性,例如j.JobDeadline> ruleDate。这需要一些测试,但可以使它起作用。或者,比较.Month .Day和.Year的三个属性(j.Deadline.Year == ruleDate.Year && j j.Deadline.Month == ruleDate.Month && j.Deadline.Day == ruleDate.Day)。虽然不是很优雅,但是可以用,因为它们只是整数。
2012年

嗯 这个想法行得通。脏但有效。如果您将其写为答案,我可以将其标记为正确。
星云

230

您可以使用EntityFunctionsTruncateTime方法将属性正确转换为SQL:Date

using System.Data.Objects; // you need this namespace for EntityFunctions

// ...

DateTime ruleData = Convert.ToDateTime(rule.data).Date;
return jobdescriptions
    .Where(j => EntityFunctions.TruncateTime(j.JobDeadline) == ruleData);


更新: EntityFunctions在EF6中已弃用,使用DbFunctions.TruncateTime


好吧,我注意到这ruleDataDateTime类型,并且j.JobDeadline已截断时间。感觉不对。没有得到异常,但也没有得到预期的结果。
星云2012年

@aneal:它返回所有记录JobDeadline具有相同的日期作为rule.data,不管什么是一天的时间。这不是您要通过查询查询实现的目标吗?为什么感觉不对?
Slauma

1
+1,我也同意以上
观点,

26
请注意,EntityFunctions在EF6 中已弃用,现在应使用DbFunctions
朱利安N

2
> EF6中的DbFunctions的命名空间是System.Data.Entitymsdn.microsoft.com/zh-cn/library/Dn220142
v=VS.113).aspx

39

对于EF6,请改用DbFunctions.TruncateTime(mydate)。


9

ef6中的“ EntityFunctions.TruncateTime”或“ DbFunctions.TruncateTime”正在工作,但在大数据中存在一些性能问题。

我认为最好的方法就是这样:

DateTime ruleDate = Convert.ToDateTime(rule.data);

DateTime  startDate = SearchDate.Date;

DateTime  endDate = SearchDate.Date.AddDay(1);

return jobdescriptions.Where(j.Deadline >= startDate 
                       && j.Deadline < endDate );

比使用部分日期要好。因为在大数据中查询运行得更快。


为此答案+1。EntityFunctions.TruncateTime(后来由代替DbFunctions.TruncateTime)通过转换为SQL来实现,其中datetime转换为字符串并被截断。与处理的记录数量成比例,这使查询运行明显变慢。
urig

3

需要包括using System.Data.Entity;。即使与ProjectTo<>

var ruleDate = rule.data.Date;
return jobdescriptions.Where(j => DbFunctions.TruncateTime(j.Deadline) == ruleDate);


1

这意味着LINQ to SQL不知道如何将Date属性转换为SQL表达式。这是因为该结构的Date属性DateTime在SQL中没有类似物。


1

它为我工作。

DateTime dt = DateTime.Now.Date;
var ord = db.Orders.Where
      (p => p.UserID == User && p.ValidityExpiry <= dt);

资料来源:Asp.net论坛


0

我有同样的问题,但我使用DateTime-Ranges。我的解决方案是将开始时间(带有任何日期)设置为00:00:00,将结束时间设置为23:59:59,因此我不必再将DateTime转换为Date,而是将其保留为DateTime。

如果只有一个DateTime,则还可以将开始时间(带有任何日期)设置为00:00:00,将结束时间设置为23:59:59,然后进行搜索,就好像它是一个时间跨度一样。

var from = this.setStartTime(yourDateTime);
var to = this.setEndTime(yourDateTime);

yourFilter = yourFilter.And(f => f.YourDateTime.Value >= from && f.YourDateTime.Value <= to);

您也可以使用DateTime-Range做到这一点:

var from = this.setStartTime(yourStartDateTime);
var to = this.setEndTime(yourEndDateTime);

yourFilter = yourFilter.And(f => f.YourDateTime.Value >= from && f.YourDateTime.Value <= to);

0

你可以得到枚举像:

DateTime todayDate = DateTime.Now.Date; var check = db.tableName.AsEnumerable().Select(x => new
        {
            Date = x.TodayDate.Date
        }).Where(x => x.Date == todayDate).FirstOrDefault();

为了应用日期过滤器,这有效地枚举了表的全部内容,这似乎是一个非常糟糕的主意!
哈维尔·拉波特

0

正如这里许多人所指出的那样,使用TruncateTime函数很慢。

如果可以的话,最简单的选择是使用EF Core。它可以做到这一点。如果不能,则截断的更好替代方法是根本不更改查询的字段,而修改边界。如果您正在执行普通的“介于”类型查询,其中上下限是可选的,则可以使用以下技巧。

    public Expression<Func<PurchaseOrder, bool>> GetDateFilter(DateTime? StartDate, DateTime? EndDate)
    {
        var dtMinDate = (StartDate ?? SqlDateTime.MinValue.Value).Date;
        var dtMaxDate = (EndDate == null || EndDate.Value == SqlDateTime.MaxValue.Value) ? SqlDateTime.MaxValue.Value : EndDate.Value.Date.AddDays(1);
        return x => x.PoDate != null && x.PoDate.Value >= dtMinDate && x.PoDate.Value < dtMaxDate;
    }

基本上,我们不是将PoDate修剪回日期部分,而是增加了查询上限和用户<而不是<=

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.