我有一些简单的代码可以从数据库中检索记录的 ELMAH 异常:
HealthMonitoringEntities context = new HealthMonitoringEntities();
IQueryable<ELMAH_Error> exceptions = context.ELMAH_Error;
if (filter.ToDate != null)
exceptions = exceptions.Where(e => e.TimeUtc <= filter.ToDate.Value.AddHours(-4));
return exceptions.OrderByDescending(e => e.TimeUtc)
.Take(filter.Size)
.AsEnumerable()
.Select(e => new ElmahException()
{
ErrorId = e.ErrorId,
Application = e.Application,
Host = e.Host,
Type = e.Type,
Source = e.Source,
Error = e.Message,
User = e.User,
Code = e.StatusCode,
TimeStamp = e.TimeUtc.AddHours(-4).ToString()
}).ToList();
}
我在这条线上遇到了一个例外:
TimeStamp = e.TimeUtc.AddHours(-4).ToString()
例外是:
LINQ to Entities does not recognize the method 'System.DateTime AddHours(Double)' method, and this method cannot be translated into a store expression.
当我.AsEnumerable()
在使用 投影之前调用时Select()
,我的序列被枚举并且我从实现的序列中进行投影IEnumerable<ELMAH_Error>
。鉴于此,为什么我不在我的投影中使用 Linq-To-Objects API,它理解AddHours()
,而不是仍然使用 Linq-To-Entities API?
更新
Jon Skeet 在这里有一篇关于这个主题的帖子:
他有这个疑问:
var query = db.Context
.Customers
.Where(c => some filter for SQL)
.OrderBy(c => some ordering for SQL)
.Select(c => some projection for SQL)
.AsEnumerable() // Switch to "in-process" for rest of query
.Where(c => some extra LINQ to Objects filtering)
.Select(c => some extra LINQ to Objects projection);
请注意,在他调用 之后AsEnumerable()
,他表示他正在切换到 Linq-To-Objects。我在我的函数中做了类似的事情,但是我收到了一个 Linq-To-Entities 异常,我以为我会针对 Linq-To-Objects API 执行。
进一步更新
来自 Jim Wooley 的博客: http: //linqinaction.net/blogs/jwooley/archive/2009/01/21/linq-supported-data-types-and-functions.aspx
“例如,以下方法显示为具有 DateTime 值的转换:Add、Equals、CompareTo、Date、Day、Month、Year。相反,不支持 ToShortDateString、IsLeapYear、ToUniversalTime 等方法。
如果您需要使用其中一种不受支持的方法,则需要将结果强制发送给客户端并在此时使用 LINQ to Objects 评估它们。您可以在查询理解的任何时候使用 .AsEnumerable 扩展方法来做到这一点。”
这不是我在做什么吗?