以下是代码示例:
Apache Tomcat 7
现在,如果 public IList<LogEntry> ReadLogs(Guid id, string name)
{
var logs = this.RetrieveLogs(id, name);
if (logs != null)
{
foreach (LogEvent logEvent in logs)
{
// bla, bla, bla
}
}
return logEntries;
}
private IEnumerable<LogEvent> RetrieveLogs(Guid id, string name)
{
try
{
FilterCriteria filterCriteria = CreateFilterCriteria();
return (from log in this.loggingProvider.ReadLogs(filterCriteria, 1)
where log.ParticipantObjects[0].ParticipantObjectId == id.ToString()
&& log.LogEventParameters[0].Value == name
orderby log.Timestamp.ToLocalTime() descending
select log).AsEnumerable();
}
catch (Exception ex)
{
this.tracer.Write(Category.Error, ex, "Error");
return null;
}
}
方法中存在异常,则会捕获并跟踪它。但是,例如,如果没有loggingProvider.ReadLogs()
,则此异常不会被捕获并在此处跟踪。它似乎与lambda表达式和闭包有关。
解释是什么?
答案 0 :(得分:15)
之前我已经说过了,我无疑会再说一遍:了解查询最重要的一点是查询是一个问题,而不是问题的答案。
您构建的查询对象不仅仅通过构建它来执行。你正在构建这个问题。在您执行查询之前,问题实际上并没有被要求和回答。并且执行在try块之外。
答案 1 :(得分:5)
loggingProvider.ReadLogs
在RetrieveLogs
内执行。但是只有当你在外部this.ReadLogs
迭代它们时才会执行所有其他lambda。
因此,在您的upper方法中抛出异常,因此无法在RetrieveLogs
内捕获。
要避免这种情况,请将AsEnumerable
更改为ToList()
或ToArray()
,以确保在返回之前实际执行查询。
答案 2 :(得分:3)
LINQ查询的IEnumerable
结果仅在枚举时进行评估。
为了将Exception
抛出到您期望的位置,您需要使用IEnumerable
之类的相关扩展方法枚举LINQ查询结果ToList()
。
作为旁注(借用Rene Vogt),您可以通过编写LINQ来避免抛出Exception
,如下所示:
return this.loggingProvider.ReadLogs(filterCriteria, 1).Where(log =>
log.ParticipantObjects.FirstOrDefault() != null &&
log.ParticipantObjects[0].ParticipantObjectId == id.ToString() &&
log.LogEventParameters[0].Value == name).OrderBy(log =>
log.Timestamp.ToLocalTime()).ToList();