LINQ to Entities 异常中不支持指定的类型成员“日期”

Posted

技术标签:

【中文标题】LINQ to Entities 异常中不支持指定的类型成员“日期”【英文标题】:The specified type member 'Date' is not supported in LINQ to Entities Exception 【发布时间】:2012-07-20 19:03:30 【问题描述】:

我在执行以下语句时遇到了异常。

 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 【参考方案1】:

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

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 有截断时间。感觉不对。没有得到异常,但也没有得到预期的结果。 @aneal:它返回所有JobDeadlinerule.data 具有相同日期 的记录,无论一天中的什么时间 .这不是您想通过问题中的查询实现的目标吗?为什么感觉不对? +1 我同意上述观点,这对于 99% 的实现来说绝对是一个更好的答案 请注意,EntityFunctions 在 EF6 中已弃用,您现在应该使用 DbFunctions EF6 中 DbFunctions 的命名空间是 System.Data.Entity : msdn.microsoft.com/en-us/library/Dn220142(v=VS.113).aspx【参考方案2】:

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

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

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

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

【讨论】:

j => j.JobDeadline.Date 呢? Date 是 JobDeadline 上的属性吗?这本身不应该导致错误 - 可能是命名冲突(但不确定)。如果该行仍然导致错误,只需将其重命名为 DeadlineDate 或类似名称。 日期是 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)。不优雅,但它可以工作,因为这些只是整数。 嗯。这个想法有效。脏但有效。如果您将其写为答案,我可以将其标记为正确。【参考方案3】:

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

【讨论】:

【参考方案4】:

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 来实现,其中日期时间被转换为字符串并被截断。这使得查询运行速度明显变慢,与处理的记录数成正比。【参考方案5】:

需要包含using System.Data.Entity;。即使使用 ProjectTo&lt;&gt; 也能正常工作

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

【讨论】:

已经回答here【参考方案6】:

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

【讨论】:

【参考方案7】:

它对我有用。

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

来源:Asp.net Forums

【讨论】:

【参考方案8】:

我有同样的问题,但我使用的是 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);

【讨论】:

【参考方案9】:

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

如果可以的话,最简单的选择是使用 EF Core。它可以做到这一点。如果你不能,那么一个更好的 truncate 替代方法是根本不更改查询的字段,而是修改边界。如果您正在执行一个正常的“介于”类型查询,其中下限和上限是可选的,那么以下方法可以解决问题。

    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 修剪回只是 Date 部分,而是增加查询上限和用户

【讨论】:

以上是关于LINQ to Entities 异常中不支持指定的类型成员“日期”的主要内容,如果未能解决你的问题,请参考以下文章

在LINQ to Entities中不支持指定的类型成员'x'。只支持初始化器实体成员和实体导航属性。

LINQ to Entities 不支持指定的类型成员“日期”。 DbFunctions.TruncateTime()

LINQ to Entities 格式化日期异常 [重复]

无法将类型“System.Nullable`1”强制转换为类型“System.Object”。LINQ to Entities 仅支持强制转换 EDM 基元或枚举类型。

在 Linq-to-Entities 查询中格式化日期会导致异常

LINQ to Entities 不支持 LINQ 表达式节点类型“Invoke”