2014-02-06 55 views
1

我有以下代码错误LINQ到实体日期时间

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)'方法,此方法不能将 转换成商店表达式。

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

+0

为什么你将日期时间值作为字符串存储在数据库中?如果你为你的值使用适当的类型会容易得多。 – MarcinJuraszek

+0

@MarcinJuraszek其实db包含格式为“yyyy-MM”的值,但我没有管理员访问该数据库 –

+0

@MarcinJuraszek感谢您的编辑以及您的兴趣:) –

回答

2

那么,错误其实很明显。在Linq中没有将ParseExact的实体翻译成SQL。请记住,实体框架在封面下将查询转换为SQL命令或一组命令组。如果EF不知道如何翻译某些内容,则会引发此错误。

一个可能的解决方案,虽然效率不高,但将IQueryable转换为IEnumerable,这将允许您执行该语句。

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

'query.ToList()'将从数据库中获取所有数据,而不仅仅是'x.Date'值,这很重要。 – MarcinJuraszek

+1

@MarcinJuraszek - 不知道模式,你不能假定表中有多个列。为了了解他自己的模式并做出适当的修改,我给了提问者信用。 –

+0

是的,我知道这是一种可能性。这就是为什么我只是评论而不是downvoting :) – MarcinJuraszek

1

恐怕你不得不从DB DATATIME值的所有string表示加载到内存:

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

并进行分析和分作为LINQ到对象查询:

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

如果您的DB已设置属性,并且x.DateDateTime您可以这样做:

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

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

+0

非常感谢Marcin。我现在会尝试 –

+0

ToList会工作,并且没有任何问题,但如果您实际上不会将它用作List,那么为什么要创建List?数组比列表更高效,因此您应该默认调用ToArray,并且只在需要时调用ToList。 – jmcilhinney

+0

@jmcilhinney我不明白为什么'ToArray'会更有效率。也许只有一个事实,即ToList()会在所有记录加载时缩小分配的数组,当ToList()将在底层数组中保留这些未使用的空间以便将来更快地进行其他插入时。 – MarcinJuraszek

0

LINQ to Entities将您的LINQ查询转换为SQL代码,然后对数据库执行该查询。这意味着您编写的代码必须能够转换为SQL代码。没有办法将DateTime.ParseExact转换为SQL代码,因此是例外。您将需要通过调用ToArray来评估一个LINQ to Entities查询,然后您可以对此执行第二个LINQ to Objects查询,并且它将理解DateTime.ParseExact。

+0

非常感谢jimcilhinney给你答案。但是,我认为如果它包含一段代码,可以更好地支持您的答案:) –

2

如果日期是在DB的格式为“YYYY-MM”,那么你可以做基于字符串排序查询,并将结果转换为datetime字符串:

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

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

+0

非常感谢蒂莫西。 Upvoted为您提供帮助:) –

+0

@JimBlum从您对其他答案的评论中,您似乎想要做的不仅仅是获取最低日期。您能否更新您的问题,提供更多关于您需要的详细信息,以便我可以提供更好的答案?我经常采取两步骤的过程,减少我的行数,并根据需要获取尽可能多的原始数据,然后到'.ToList()',然后安全地使用我喜欢的内存集合中的所有非SQL兼容调用。 –