在 Linq-to-Entities 查询中格式化日期会导致异常
Posted
技术标签:
【中文标题】在 Linq-to-Entities 查询中格式化日期会导致异常【英文标题】:Formatting date in Linq-to-Entities query causes exception 【发布时间】:2011-08-15 21:54:47 【问题描述】:我有提交日期时间的实体类,我想选择不同的 'mon-yyyy' 格式日期时间文件值并填充下拉列表。
下面的代码给了我错误:
var env = db.Envelopes.Select(d => new
d.ReportDate.Year,
d.ReportDate.Month,
FormattedDate = d.ReportDate.ToString("yyyy-MMM")
).Select(d => d.FormattedDate)
List<SelectListItem> _months = new List<SelectListItem>();
foreach (var mname in env)
_months.Add(new SelectListItem() Text = mname, Value = mname );
错误信息:
LINQ to Entities 无法识别 方法'System.String ToString(System.String)' 方法,以及 这个方法不能翻译成 商店表达式。
如何更正此错误消息?
谢谢 SR
【问题讨论】:
【参考方案1】:请记住,您的查询将被转换为 SQL 并发送到数据库。查询不支持您尝试格式化日期,这就是您看到该特定错误消息的原因。您需要检索结果,然后在数据具体化后进行格式化。
一个选项是直接选择日期。在迭代结果时,在将其添加到列表时对其进行格式化。但是你也可以通过方法链在单个语句中实现格式化日期列表的构建。
List<SelectListItem> _months = db.Envelopes.OrderByDescending(d => d.ReportDate)
.Select(d => d.ReportDate)
.AsEnumerable() // <-- this is the key method
.Select(date => date.ToString("MMM-yyyy"))
.Distinct()
.Select(formattedDate => new SelectListItem Text = formattedDate, Value = formattedDate )
.ToList();
.AsEnumerable()
方法将强制对数据库执行查询的第一部分,其余部分将处理内存中的结果。
【讨论】:
@Anthony Pegram:感谢您的回复。从您的代码中,我想按 ReportDate 的降序获取不同的值和顺序。我需要在你的代码中添加这两个。 我已经更新了答案,包括在AsEnumerable()
调用之前的降序日期排序和不同的日期。然后这些将成为 SQL 的一部分并由数据库处理。
@Anthony Pegram,抱歉我的问题不清楚。我想获得不同的 'yyyy-MMM' 值,而不是不同的报告日期。
@sfgroups,明白了。在这种情况下,您会将.Distinct()
移动到.AsEnumerable()
之后。我会再次更新。
2011-03-23 2011-04-19 2011-04-26 2011-05-26
我有这些价值。期待这个输出:May-2011 Apr-2011 Mar-2011
【参考方案2】:
这里有一个替代方案:
.Select( p -> SqlFunctions.StringConvert((double)
SqlFunctions.DatePart("m", p.modified)).Trim() + "/" +
// SqlFunctions.DateName("mm", p.modified) + "/" + MS ERROR?
SqlFunctions.DateName("dd", p.modified) + "/" +
SqlFunctions.DateName("yyyy", p.modified)
显然DateName("MM", ..)
拼出了月份名称,其中DatePart("mm", ..)
提供了一个数值,因此StringConvert( )
,但是这个左边用空格填充了结果,因此.Trim()
。
就像 Anthony Pegram 上面所说的那样,这发生在数据库中而不是 C# 中(.AsEnumerable()
将所有本地数据提取到 C#,因此请确保在使用之前过滤数据。)
显然,您希望稍微重新排列输出以适合 yyyy-MM
,并使用 DatePart 作为数字或使用 DateName 作为月份名称。
【讨论】:
喜欢这个答案,但是当人们使用类而不指示可以找到该类的命名空间时,它会杀死我。 SqlFunctions 位于 System.Data.Objects.SqlClient 命名空间中。您需要在项目中引用 System.Data.Entity 程序集才能找到它。【参考方案3】:这是使用常见 dd/MM/yyyy 格式的替代方案。 使用 Entity Framework 5 在 SQL Server 2012 上确认
invoices.Select(i => new
FormattedDate = ( EntityFunctions.Right(String.Concat(" ", SqlFunctions.StringConvert((double?) SqlFunctions.DatePart("dd", i.DocumentDate))), 2)
+ "/"
+ EntityFunctions.Right(String.Concat(" ",SqlFunctions.StringConvert((double?) SqlFunctions.DatePart("mm", i.DocumentDate))), 2)
+ "/"
+ EntityFunctions.Right(SqlFunctions.StringConvert((double?) SqlFunctions.DatePart("yyyy", i.DocumentDate)), 4)
).Replace(" ", "0")
以带前导零的 dd/MM/yyyy 格式生成日期。
【讨论】:
【参考方案4】:我使用了一种解决方法来手动构建包含yyyy
和MM
的格式。如果它可以帮助某人(至少暂时),我想在这里提一下:
FormattedDate = d.ReportDate.Year.ToString() + "-" + d.ReportDate.Month.ToString()
这使得格式yyyy-MM
【讨论】:
以上是关于在 Linq-to-Entities 查询中格式化日期会导致异常的主要内容,如果未能解决你的问题,请参考以下文章
为啥 LINQ-to-Entities 将此查询放在子选择中?
Linq-to-Entities:带有 WHERE 子句和投影的 LEFT OUTER JOIN
如果存在-UPDATE-else-INSERT 与 Linq-to-Entities?