As Eric Lippert described in this article, yield return
is not allowed within try/catch
clauses.
Is there a nice way I could get something like this, without having to write my own IEnumerator
by hand:
public IEnumerable<Data> GetData()
{
var transaction = Session.BeginTransaction());
try
{
IQuery q = CreateQuery(session);
foreach (var result in q.Enumerable())
yield return ProjectResult(result); // <-- doesn't work
session.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
throw;
}
finally
{
transaction.Dispose();
}
}
Yes, we can write a return statement of the method in catch and finally block. There is a situation where a method will have a return type and we can return some value at any part of the method based on the conditions.
In a try-catch-finally block that has return statements, only the value from the finally block will be returned. When returning reference types, be aware of any updates being done on them in the finally block that could end up in unwanted results.
When you have methods that do multiple things you are multiplying the complexity, not adding it. In other words, a method that is wrapped in a try catch has two possible outcomes. You have the non-exception outcome and the exception outcome.
Return your Dictionary end of your try block, return null from your catch . And every time you call this function check for returning value. If it's null then that means something bad happened. Because returning a null Dictionary is the same as returning null directly.
I'd just change the transaction-handling logic like this:
public IEnumerable<Data> GetData()
{
var transaction = Session.BeginTransaction();
bool rollback = true;
try
{
IQuery q = CreateQuery(session);
foreach (var result in q.Enumerable())
{
yield return ProjectResult(result);
}
rollback = false;
session.Commit();
}
finally
{
if (rollback)
{
transaction.Rollback();
}
transaction.Dispose();
}
}
Or if your transaction supports the idea of "dispose means rollback unless it's commited":
public IEnumerable<Data> GetData()
{
using (var transaction = Session.BeginTransaction();
{
IQuery q = CreateQuery(session);
foreach (var result in q.Enumerable())
{
yield return ProjectResult(result);
}
// Commits the tnrasaction, so disposing it won't roll it back.
session.Commit();
}
}
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