【问题标题】:Error Linq to Entities Datetime错误 Linq 到实体日期时间
【发布时间】:2014-03-02 21:00:58
【问题描述】:

我有以下代码

var dates = query.Select(
                 x => DateTime.ParseExact(x.Date, "yyyy-MM", CultureInfo.InvariantCulture));

var minDate = dates.Min(x => x);

但是当我执行它时,我得到了异常

System.Data.Entity.dll 但未在用户代码中处理

附加信息:LINQ to Entities 无法识别该方法 'System.DateTime ParseExact(System.String, System.String, System.IFormatProvider)' 方法,并且该方法无法翻译 到商店表达式中。

我做错了什么?我该如何解决这个问题?

【问题讨论】:

  • 为什么将日期时间值作为字符串存储在数据库中?如果你为你的值使用正确的类型会容易得多。
  • @MarcinJuraszek 实际上数据库包含格式为“yyyy-MM”的值,但我没有对该数据库的管理访问权限
  • @MarcinJuraszek 感谢您的编辑和关注 :)
  • 所以 x.Date 实际上不是 DateTime 而是一个字符串?
  • @rikitikitik 非常感谢您的评论。是的。这也显示在异常错误中。

标签: c# sql linq entity-framework datetime


【解决方案1】:

嗯,错误其实很清楚。在 Linq 中没有将 ParseExact 的实体转换为 SQL。

请记住,实体框架在幕后会将查询转换为 SQL 命令或命令集。如果 EF 不知道如何翻译某些内容,则会引发此错误。

一种可能的解决方案,虽然不是非常有效,但将 IQueryable 转换为 IEnumerable,这将允许您执行语句。

var dates = query.ToList().Select(
             x => DateTime.ParseExact(x.Date, "yyyy-MM", CultureInfo.InvariantCulture));

【讨论】:

  • query.ToList() 将从数据库中获取所有数据,而不仅仅是x.Date 值,这很重要。
  • @MarcinJuraszek - 在不知道架构的情况下,您不能假设表中的列不止一列。我感谢提问者知道他自己的架构并进行了适当的更改。
  • 是的,我知道这是可能的。这就是为什么我只是发表评论而不是投反对票:)
  • 非常感谢埃里克。我非常感谢你!你成功了!谢谢!刚投了赞成票。我对这个解决方案非常满意,但仅仅因为我想做每一件事都非常高效,你能不能也想出一些更有效的方法?再次感谢你
  • @JimBlum - 好吧,在您的情况下,如果您只想找到最早的日期,您可能只需订购该列,然后只需获取第一个条目。如果您在 DateTime 对象中实际上不需要它,那么您甚至不需要解析它。
【解决方案2】:

如果数据库中的日期是“yyyy-MM”格式的字符串,那么您可以根据字符串排序进行查询并将结果转换为日期时间:

var minDateString = query.Select(x => x.Date).Min();
var minDate = DateTime.ParseExact(
    minDateString, 
    "yyyy-MM", 
    CultureInfo.InvariantCulture
);

许多系统都依赖于“yyyy-MM-dd hh:mm:ss”的自然字符串排序,您也可以轻松地依赖该排序的子集。

【讨论】:

  • @JimBlum 来自您在其他答案上所做的 cmets,看来您想做的不仅仅是获得最短日期。您能否用您需要的更多详细信息更新您的问题,以便我提供更好的答案?我经常采用两步流程,减少行数并获取所需的原始数据,然后转到.ToList(),然后我可以安全地在内存集上使用我喜欢的所有非 SQL 兼容调用。跨度>
【解决方案3】:

恐怕您必须将数据时间值的所有 string 表示从 DB 加载到内存:

var dates = query.Select(x => x.Date).ToList();

并执行解析和 min 作为 LINQ to Objects 查询:

var min = query.Min(x => DateTime.ParseExact(x, "yyyy-MM", CultureInfo.InvariantCulture));

如果您的数据库被设置为属性并且x.DateDateTime,您可以这样做:

var dates = query.Select(x => x.Date);
var min = dates.Min();

这将被翻译成适当的 SQL 查询并让MIN() 由数据库计算,因此您不必将所有数据提取到应用程序内存中。

【讨论】:

  • 非常感谢马辛。我现在就试试
  • ToList 可以工作,实际上并没有什么问题,但是如果您实际上不打算将它用作列表,那么为什么要创建一个列表呢?数组比列表更有效,因此您应该默认调用 ToArray,并且仅在需要时调用 ToList。
  • @jmcilhinney 我看不出ToArray 在这里效率更高的任何理由。也许只是一个事实,ToArray() 会在加载所有记录时缩小分配的数组,而ToList() 会将这些未使用的空间保留在底层数组中,以便将来更快地进行其他插入。
  • 这给了我一个语法错误"Cannot convert lambda expression to type ulong because it is not a delegate type"
  • 现在检查。我注意到x => x => 是偶然出现的。
【解决方案4】:

LINQ to Entities 获取您的 LINQ 查询并将其转换为 SQL 代码,然后针对数据库执行该代码。这意味着您编写的代码必须能够转换为 SQL 代码。无法将 DateTime.ParseExact 转换为 SQL 代码,因此出现异常。您将需要通过调用 ToArray 来评估 LINQ to Entities 查询,然后您可以对其执行第二个 LINQ to Objects 查询,它将理解 DateTime.ParseExact。

【讨论】:

  • 非常感谢 jmcilhinney 的回答。但是,我认为如果包含一段代码,您的答案可能会得到更好的支持:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-12
  • 2011-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多