CQRS & MediatR | ASP.NET 6 REST API Following CLEAN ARCHITECTURE & DDD Tutorial | Part 6

preview_player
Показать описание


Follow me on 'em socials:

What is this series?
We'll build a REST API following Clean Architecture & Domain-Driven Design principles completely from scratch.
We will use .NET 6, EF Core, and common patterns such as CQRS, unit of work, repository, mediator, and more 💪🏽
We'll also use some awesome open-source libraries such as MediatR, FluentValidation, ErrorOr, Throw, Mapster, and more.
The developing environment will be visual studio code & dotnet CLI only. We will use awesome vscode plugins for everything from sending HTTP requests to connecting to our SQL database, debugging, and peeking at JWT tokens.
We will code and refactor multiple times to tackle the many concepts I want to teach. When the series will be over, you'll have a good understanding and intuition on how to use these patterns & libraries in your industry-level applications.

How often will a new part come out?
Once or twice a week.

What are we doing today?
Today we'll split our application logic following the CQRS Design Pattern.
Then, we'll introduce the package MediatR which will play nicely with this Design Pattern and help us split our logic by feature, which will make the use cases in our application layer clear.

Give MediatR a ⭐:

#dotnet

00:00. CQS (Command Query Separation)
01:40. CQRS (Command Query Responsibility Segregation)
02:27. CQS & CQRS Misconceptions
03:18. Implementing CQRS
06:57. The Problem with CQRS in large systems
07:33. Splitting the logic by Feature
09:07. MediatR NuGet package
10:02. Implementing MediatR Command
11:35. Implementing MediatR Command Handler
13:07. Implementing MediatR Query
13:36. Implementing MediatR Query Handler
14:30. MediatR Dependency Injection
16:12. Using the Mediator object
16:34. Mediator pro tip
18:00. Domain Models with CQRS Query path
Рекомендации по теме
Комментарии
Автор

CQS: Method can either change state or return a value - not both
CQRS: Like CQS, but not as strict regarding the return value, the main emphasis is on having a clear boundary between Commands and Queries
Mediator Pattern: Promote loose coupling between objects by having them interact via a mediator rather than referencing each other
MediatR: An in-memory implementation of the Mediator pattern, where MediatR requests & MediatR handlers are wired up during the DI setup
Splitting Logic By Feature: Having each use case in a separate file

What we demonstrated today is using the MediatR package to implement the Mediator design pattern. We separated our use cases into different files, and following CQRS, we defined clear boundaries between our Commands and Queries by nesting Command Handlers and Query Handlers in different folders.

Please remember that the definitions above follow the original definitions of the people who coined the terms, not interpretations of others over the years.

Hope that clears up any confusion 🙂

amantinband
Автор

I've watched many many people online but you are foremost the best one!

necatiakpnar
Автор

Update on how you should implement the DI in Mediatr starting version 12.0.0:

services.AddMediatR(config =>

wbipbeu
Автор

Hands down best explanation of CQRS I have found with non-trivial practical example to understand how it is implemented. Thank you!

emilzyka
Автор

good first steps in the "right" direction, when behaviours will kick in to have logging, transactions, validations, and so on.
A long way to go even considering DDD but I'm sure people will enjoy the final result!
Just an advice to people who are watching this series (but in general any dev video): after having watched a vid, do your own research on the topic, don't assume what you are actually listened to is good enough or a perfect fit for your needs because things will evolve next episodes and will change a lot of things, also there isn't a silver bullet so it's worth going deeper into the subjects to understand the ins and outs. You'll find yourself changing your approach every now and then: it's a sign you are learning and that's the good thing. The "bad" side is that the learning path never ends :) (actually having to learn everyday is one of the things I like the most about this job and I think every good programmer need to have this approach)

mithrilman
Автор

I love the MediatR library. I actually didn’t know you could use just use the ISender instead of the full IMediator to get a slimmed down mediator if that’s all you use if for. Another great VOD in the books!

kmcdo
Автор

When I met the MediatR for the first time (at work in one of our projects) I was shocked how beautiful this library (and CQRS pattern of course) is. It makes Controllers so clean and small with no effort.

I hope for the 'Notification' part in MediatR 😊

patrykk.
Автор

I'm following this course using .Net 8, so far so good. This was an enlightening section, thanks for putting it together.

TrOgaN_
Автор

There's no doubt that the series is great, but the comments and answers are also valuable as I learn from them.

Hassanlou
Автор

I need more! This series is fantastic, cant get episodes fast enough :D

silvertek
Автор

Another amazing video, can't wait for the next one :D

TiagoPereira-rfjf
Автор

Amichal - great video as usual. Great, concise and comprehensible info.

willhunt
Автор

Honest question. But what value CQRS and separating things into commands and queries actually bring? Underneath it's all just MediatR.IRequest - so they are handled exactly the same way by the command bus/Mediator. The handlers ultimatelly don't really differ. Queries, as you said in one of the comments below, can morph into commands, for example when Login Query needs to also update DB with amount of login attempts - it becomes a Command, requiring a refactor which in some cases might be a breaking change.
I could see it having some value if it was, I dunno, an interface for repository - where we'd only query data from repository, or update it. But that's usually unrealistic, and Commands/Queries quickly spread into business logic (like here with Login/Create Token requests).
Since Commands also return values they are, essentially better Queries anyway.
Also can Query Handlers issue Commands and indirectly change values in the store? Or do they need to be refactored into Commands too now?

I'm asking all that, because I'm at the tail end of massive refactor, removing CQRS from quite big service, in my company. After few years of development, we realized separating things into Commands and Queries didn't add anything, except for confusion. Queries once created weren't refactored into Commands, if a need arose, Commands sometimes acted like Queries, Queries like Commands, and it all become a massive mess. We tried enforcing restriction, by having dedicated interfaces for Commands/Queries, that restricted what they can return etc. We tried separating business logic into very granular commands/queries, but that become overwhelming - for ex. Authentication - Query for info if user can be authenticated, send Command to update it's attempt number, send query to check if a refresh token is available, if yes, send command to invalidate the token, send command to generate new access/refresh token, send query to get the tokens etc.. This become unwieldly. With so many granular commands/queries it also become increasingly hard to keep track of which are still actually used, as the development progressed..

So now we are throwing it all away, and scaling back the granularity of each MediatR.IRequest. We just have "high level" request send from API endpoint/Controller to a MediatR handler, which handles it, and if it needs more granularity - it sends more requests for other handlers to deal with. That loose coupling that MediatR provides is still there and this is great. But any separation between Commands and Queries is gone.

DemoBytom
Автор

Your video are pure gold! Thank you! I'm switching from Game Dev to Backend development and your videos are helping me a lot. I'm also studying DDD so I can't wait to see more about!

evilTano
Автор

Just found this series this week. Very interesting and informative. Much thanks for creating this series and keep up the good work!

wvanlosser
Автор

The pacing is amazing for people like me who are impatient lol, seriously these videos are wonderful.

urzadek
Автор

Thanks, this how I've been implementing my apps. So much clearer to reason about the code base.

nthonymiller
Автор

Your trainings are great, thank you very much, we would be glad if you support these lessons with real real database.

ugursesen
Автор

Good job as always. I can`t wait for your upcoming videos.

afsanehhazeghi
Автор

As far as I remember Pascal language had basic segregation to procedures(doesn't return value) and functions(returns value)

xelaksal