Transaction Management With Mediator Pipelines in ASP.NET Core

Manage Entity Framework Core transactions when handling commands

João Simões
Nov 7, 2020 · 5 min read

When implementing a simplified CQRS service, which usually has a single database but still separates commands from queries, the mediator pipeline can be used to manage transactions when processing commands, ensuring changes will be implicitly committed unless an exception is thrown.

Implementing a pipeline for transactions has some key advantages even when using Entity Framework Core or other ORM that tracks and flushes changes at a single point in time.

Because the command handler is executing inside an implicit transaction, the developer is free to flush their changes as it sees fit knowing that any exception will rollback the changes. This is very helpful when it wants to cancel the flow when some business rules aren’t meet and could only be checked after changing the system state. Optimistic concurrency is a good example where you may want to flush your changes before leaving the handler so you know exactly what entity failed and can send a more detailed message to the user, which is the usual approach when implementing a dedicated Backend for Frontend service.

Also, ORMs are very good at abstracting database access but can’t solve more edge cases, specially when performance is a requirement. Being able to use a more lightweight library (e.g. Dapper) to do some bulk operations and using the ORM context connection inside the same transaction will remove the need to use the and reduce some application complexity.

Ensuring transactions are properly managed around the handler execution ensure the application architecture is be more robust and will be able to handle more edge cases.

The project

This article will be based on my previous ones that explained how to use the mediator and implement transversal behavior with pipelines. As a reminder, we implemented an endpoint to manage products with the following:

  • GET /products — search for products using some filters ();
  • GET /products/{id} — get a product by its unique identifier ();
  • POST /products — create a product ( and );
  • PUT /products/{id} — update a product by its unique identifier ( and );
  • DELETE /products/{id} — delete a product by its unique identifier ( and );

You can check them out here:

The source code is available on GitHub, feel free to give it a look.

Entity Framework Core transactions

Entity Framework Core has support for explicit transaction management, which works in a similar way to ADO.NET or the class.

You can get a disposable instance of by invoking the method , available from the database property. The transaction can be either committed or rolled back, either by explicit invocation or by disposing the instance before any commit.

As stated before, this can be very helpful if must be invoked multiple times inside the unit of work operation and you want to ensure exceptions will rollback data changes.

In the example above if an exception was thrown after the first every changes would be reverted because the transaction would be disposed without an explicit call to commit.

We are going to leverage on this behavior to implement the pipeline.

The pipeline

Since only commands mutate system state, we are going to use the command pipeline to enforce a transaction for the next pipelines in the chain up until the handler.

The pipeline behavior will be:

  1. Intercept any command;
  2. Create a new with ;
  3. Invoke the next pipeline inside the scope;
  4. If no exception is thrown, flush all changes and commit;
  5. Dispose the transaction;

I’ll also include some commented code incase you want to be sure the queries never mutate the system state. Prevention is better than cure…

Inside the folder create a class extending (because we only need some of the methods):

Open the file and add the after the , preventing the opening of transactions that could be immediately closed if the command had invalid data.

Since this examples are using the in-memory database provider for Entity Framework Core, which does not support explicit transactions, we are also going to ignore them for test purposes.

Now that we have a transversal behavior that manages transactions and flushes all context changes to the database, we can remove from all command handlers the explicit calls to :

Speeding things up!

Because this is a pipeline we use very often in most of our APIs, there is already a NuGet available that allows to open an explicit Entity Framework Core transaction for commands, events or queries, depending your needs.

To use it, just open the NuGet package manager and install the package :

Open the file and register the pipeline with the extension method . Explicit transactions are disabled by default, so you only need to enable them for commands.

When using all the NuGets mentioned on my previous articles, the file should be similar to this:

Conclusion

I hope this article gave you a good idea on how to use mediator pipelines to simplify the management of Entity Framework Core transactions, making the implementation of command handlers less error prone since developers won’t forget to flush changes to the database (that behavior will be implicit unless an exception is thrown).

Even if your application is using another ORM or other lightweight libraries (e.g. Dapper), you can easily implement your own pipeline.

I also made an article about auditing user actions with pipelines, you may also find it helpful:

The Startup

Get smarter at building your thing. Join The Startup’s +794K followers.

Sign up for Top 10 Stories

By The Startup

Get smarter at building your thing. Subscribe to receive The Startup's top 10 most read stories — delivered straight into your inbox, once a week. Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

João Simões

Written by

Solutions Architect trying to solve world “problems”!

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +794K followers.

João Simões

Written by

Solutions Architect trying to solve world “problems”!

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +794K followers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store