Skip to content

Handing errors and exceptions

Jon P Smith edited this page Feb 14, 2022 · 1 revision

A GenericEventRunner event can have an error, and if that happens you need to decide what you want to do. The sensible solution for Before and During events is to stop the database update, which is what the library does. But for the After events its not such a clear case: most likely you don't want the After events to undo the database change, but in some cases you might want to undo the database change.

In this document details the options for handing errors in events so that you are clear on how to handle errors within your events.

Before and During event handlers

With the Before and During event handlers you have two options for handling errors:

  • Return a IStatusGeneric result containing errors - useful if you want to show a user-friendly error to the user.
  • Throw an exception.

In both cases the saving of the database doesn't happen. If the even throws an exception it is up to you to handle that, but your event returns a IStatusGeneric also provides extra features to capture the error(s), as shown below.

How to return errors from a Before or During event handler

The Before and During event handlers return a IStatusGeneric which, if its not null, contains the status of the event handler (see GenericServices.StatusGeneric).

NOTE: if the returned status is null, then it is considered as a successful status. This makes writing events that don't return errors simpler.

To return a IStatusGeneric result you need to create a new StatusGenericHandler class. By default, this status have no errors in it.

var status = new StatusGenericHandler();

There are a few ways to add an error (see this document), but the normal way is status.AddError("-- your error message --"). See this example of using the status inside a event handler.

How to pick up the IStatusGeneric errors

If you call SaveChanges or SaveChangesAsync

If your event handler or your SaveChanges\SaveChangesAsync exception handler (see this link returns a status with errors it will throw an GenericEventRunnerStatusException. You have two ways to get to the errors

  1. The GenericEventRunnerStatusException message contains a list of all the error messages, delimited by Environment.NewLine
  2. Your DbContext class has a IStatusGeneric<int> StatusFromLastSaveChanges property which contain the status.

Using SaveChangesWithStatus/Async

If you are using the IStatusGeneric a lot, then you can call SaveChangesWithStatus or SaveChangesWithStatusAsync methods which are the same as SaveChanges\SaveChangesAsync, but returns a status.

Before events and statuses

By default, the first status that has an error will return the error, but sometimes it useful to get all the errors from all of the Before events. This is especially useful if an executing a Before event create another Before event (this are known as saga), in which case its worth getting all the errors across all the Before events.

For this case the GenericEventRunnerConfig contains a StopOnFirstBeforeHandlerThatHasAnError that if set to false will run all the events and returns a single IStatusGeneric containing all the errors from all the events that returns a status with an error - see Configuration > Managing errors.

After events

After events are assumed to not have an error, so they don't return a IStatusGeneric result. Of course an After event could throw an Exception, but whether the database update is executed is indeterminate. Here are your options:

  • To make sure the database update is executed, you must ensure no Exception was thrown by an After events, e.g. wrap your code in a try \ catch.
  • To make sure the database update isn't executed, you use a transaction and throw an Exception, which will stop the transaction Commit method from being called.

Clone this wiki locally