Using MediatR Pipeline Behaviors For Database Transactions

preview_player
Показать описание
Database transactions are very important when it comes to the consistency of our apps. That's why in a setup with MediatR handlers we very often have the handler method cluttered with database transaction related code. But what if we use MediatR pipeline behaviors to wrap handlers into database transactions?
#dotnet #csharp #aspnetcore #mediatr

Join this channel to get source code access and other perks:

Content
1. Intro: 00:00
2. Cluttered MediatR handlers: 00:10
3. Db transactions in MediatR pipelines: 01:58

Also follow me here (especially if you are a self taught developer):

My setup:
Рекомендации по теме
Комментарии
Автор

You didn't provide a full explanation here. How do you register the pipeline behavior so that it is used by mediatr for example? If you use blazor and you have a dbContextFactory instead which is Scoped, will this pipeline still work considering that here you set the context instance to be transactional, but each handler in blazor will have it's own context then so doing it here is redundant unless you somehow pass the same context down the pipelines.

tapesteer
Автор

You could debug the code to show how it works at runtime.

alessandrohudson
Автор

❤ this s what I was looking since long time

arunbm
Автор

is it possible to use with INotificationHandler as well?

pandita.express
Автор

You can try to validate this action when clients run the command process because on the queries process you don't need transactions.

codingwithjunior
Автор

I'm not sure if this was contrived to show an example and not how you would really code such a handler, but this is not how I would code that handler, especially if using EF.

The EF model should have a navigation property on the payment or the authorization or both so you can create the PaymentAuthorization and relate it to the payment, from one side or the other, up to you.

Another option is to use client generated IDs. ULID or GUID so you can assign the FK before making the round trip to the server.

This way you have a single unit of work that is saved atomically in a single transaction by default in EF core.

Even better, give your handler one responsibility, to create the Payment and raise a PaymentCreatedEvent domain event, then process your events in your savechanges() override. This will also make save changes a single atomic action with its inherent transaction. (once again client generated ids or navigation property needed to do it this way)

I think another issue you will have is you will have to add some type of marker interface for your requests because you don't want to use the transaction handler in every mediatr request because not every handler will need a transaction. This is cognitive load for your dev team, to remember to add this marker interface, or use an IDatabaseTransactionRequest instead of IRequest, whatever.

Bottom line, magic database, transaction handler, and also event magic SaveChagnes (which I've also seen) are yuck in my opinion.

pilotboba
Автор

Do you have to register DbTransactionPipeline
Handler on the Container?

frankbanini
Автор

Don't you end up with nested transactions if you call another queries/commands from your handlers?

lukash
Автор

Will this work if there are several repositories inside the handler?

igorilyichyov
Автор

To be fair, it is a good approach, but I would hesitate to use it if I had to deal with distributed transactions scenarios…

vasiliioleinic