Here is the code example:
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;
}
}
Now, if there was an exception inside of loggingProvider.ReadLogs()
method, it will be caught and traced. But if, for example, there is no ParticipantObjects[0]
, this exception won't be caught and traced here. It seems that it has something to do with lambda expressions and closures.
What is the explanation?
What happens if an exception is not caught? If an exception is not caught (with a catch block), the runtime system will abort the program (i.e. crash) and an exception message will print to the console.
Exceptions that Can't be Caught One such exception is the limit exception ( System. LimitException ) that the runtime throws if a governor limit has been exceeded, such as when the maximum number of SOQL queries issued has been exceeded.
Java does not allow us to catch the exception twice, so we got compile-rime error at //1 .
If an exception does not have a matching catch clause, the current method terminates and throws the exception to the next higher level. If there is no matching catch clause at any higher level, then the program terminates with an error. Your program can do anything with the exception object that it chooses to.
I have said it before and I will undoubtedly say it again: the most important thing to know about a query is that a query is a question, not the answer to the question.
The query object you've built does not execute merely by building it. You are building the question. The question does not actually get asked and answered until you execute the query. And the execution is outside the try block.
loggingProvider.ReadLogs
is executed inside RetrieveLogs
. But all the other lambdas are executed only when you iterate over them in the outer this.ReadLogs
.
So the exception is thrown in your upper method, and so cannot be catched inside RetrieveLogs
.
To avoid this, change AsEnumerable
to ToList()
or ToArray()
to ensure the query is actually executed before returning.
An IEnumerable
result from a LINQ query is only evaluated when it is enumerated.
In order for the Exception
to be thrown where you expect, you need to enumerate the LINQ query result IEnumerable
using one of the relevant extension methods like ToList()
.
As a side-note (borrowing from Rene Vogt) you could avoid the Exception
being thrown by writing your LINQ as follows:
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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With