What a Tutorial man !!! Crisp and sharp and no bullshit ... Love you Bro !!!
@blablin2 жыл бұрын
I have just changed my job and jumped from 10 year old .NET project to the modern ones. I am totally overwhelmed by all of the abstraction going on. This video really helped me to grasp the approach our seniors used to get the project going. Thank you so much.
@matheusrodrigues43753 жыл бұрын
Dude!!!! I'm pretty sure you won't read this comment. But I gotta tell you, this tutorial saved my carrer!!!!!! I was about to lose hopes on understanding this kind of architecture!!! And after watching this, I can even explain to other people how this thing works!!! Thanks a lotttt, hugs from Brazil!!!!! KEEP UP THE AWESOME WORK!!!
@jonowilliams263 жыл бұрын
I read all my comments! I’m really glad this helped. Thanks heaps for the support 👍
@zakariabenmassaoud3 жыл бұрын
Really the best cqrs video! Adding records is the most clean thing! Thank you again!
@jonowilliams263 жыл бұрын
Thanks ! Glad you liked the video 👍
@niroshanmanoharan42953 жыл бұрын
A time-saving video. great informative video. Thank you!
@jonowilliams263 жыл бұрын
Thanks a lot !
@CarlosVasquez-ff5yj Жыл бұрын
With this video I did understand the CQRS principle. Many thanks.
@Aryevang2 жыл бұрын
Short and simple. Just what I needed.
@WikkiOnIlluminati3 жыл бұрын
This the only "ONE" best video which explain in simple way about CQRS. Impressive and keep it up
@jonowilliams263 жыл бұрын
Thanks heaps ! Appreciate the positive feedback
@whoiam63953 жыл бұрын
Such a great guide! Super easy explanation & also I do like that you are showing how to use the new C# 9 features!!! AWESOMEEE THANKS!
@jonowilliams263 жыл бұрын
Glad you liked it 🤙
@paikesitics3 жыл бұрын
7:02 The building blcok (my bookmark)... thank Jonathan!
@ashbjorn3 жыл бұрын
Thanks a lot Jona for the clear video without diving in to too much abstraction right away! Been wanting to try out this patterns for a while but always bailed out because it felt 'heavy' to get in to, this video shines a different light, cheers for that mate. One small comment I had when you brought up the Read vs Write DB consideration, is to utilize the option to separate the Read and Write queries through connection strings, by setting the 'Application Intent' property to 'ReadOnly'. This is especially prevalent when dealing with scaled instances where you can have access to a dedicated read-only copy (node) of your (master) database. Granted not everyone will be running Availability Groups, but this setup at least takes care of the 'syncing' automatically and can help a lot by not having to deal with row or table locks etc. (Sorry if this is a bit much).
@jonowilliams263 жыл бұрын
Hey Ashbjorn, thanks for the positive feedback ! I really appreciate it. In regards to your questions about separating your read database and write database. So for example if your application is very read heavy you might have a read database which has a very de-normalised schema in order to avoid having to join on multiple tables etc to make queries as fast as possible. But on the write side, it’s normalised and doesn’t have any redundant data. The issue is trying to keep the read database in sync with the write database. A common solution is to use events, they can be in memory using MediatR or via an event bus such as RabbitMQ. So when the write database gets updated, an event will be published and an event handler will handle the event and update the read database accordingly. Hope this answered your questions 👍
@tyaramis3 жыл бұрын
The best video about CQRS that I have watched sofar.
@jonowilliams263 жыл бұрын
Thanks ! Appreciate the positive feedback!
@redmizaki58383 жыл бұрын
Thank you so much bro! I really wish you carry on with the separate databases thing you mentioned in the beginning.
@donmikkodanm.olmillo81543 жыл бұрын
Thank you for this one! It really helps me a lot, especially on my work. I'm still a very new beginner towards .NET 5 and Web API. Kudos to you Jonathan!
@jonowilliams263 жыл бұрын
Thanks for the positive feedback
@JoeyBob1123 жыл бұрын
Really enjoying these tutorials. Presentation style is on point, I totally follow whats happening and why. Thank you :)
@jonowilliams263 жыл бұрын
Thanks heaps ! Glad you like the videos !
@athul94363 жыл бұрын
Awesome 👍👍. I have tried multiple other videos to understand the concept and this is the only one I found simple enough to feed my dumb brain
@vachm6663 жыл бұрын
Good job man, I was looking for something easy to digest for my jr developers.
@jonowilliams263 жыл бұрын
Thanks a lot ! Glad it helped
@AjithKumarRS3 жыл бұрын
just watched all videos in this channel.. you deserve more subscribers.. you'll be there soon. :) keep these videos coming...
@jonowilliams263 жыл бұрын
Thanks a lot ! I just need to be more consistent with making videos 😂
@AjithKumarRS3 жыл бұрын
@@jonowilliams26 please add design patterns to your videos list if possible.
@oopcoders93772 жыл бұрын
This is a really well made video. Very easy to follow along.
@olaamigoify3 жыл бұрын
Nicely done. Clear and concise. Gracias.
@jonowilliams263 жыл бұрын
Thanks ! Glad you liked the video !
@bunnybbyboo3 жыл бұрын
Your setup is so clean :0
@Scott-oe7dv2 жыл бұрын
I wish you'd make more videos, your way of teaching is amazing!
@Abdullah_khan3333 жыл бұрын
so simple, easy to understand in minutes instead of hours. subscribed. 👍
@Suecia20202 жыл бұрын
Excellent travail .... maintenant j'ai pu le comprendre merci
@athuljk26458 ай бұрын
Explained in detail and Thanks a lot !!
@deivid773 жыл бұрын
Love MediatR!. It's so clean & easy. Thank you for the video.
@cnikolov3 жыл бұрын
Awesome, this is actually the first thing I thought about when I saw the record feature, with mediatr it was a bit of a pain in the past to map the objects correctly
@mcnielviray3 жыл бұрын
I loved the practice you pointed out .. I will definitely implement the practice for code discoveranility. Thanks
@jonowilliams263 жыл бұрын
Thanks ! Glad it helped 👍
@georgeq50423 жыл бұрын
Hello Jonathan! Thanks a lot for the great video! It is very accurate and easy to follow.
@jonowilliams263 жыл бұрын
Thanks ! Appreciate the positive feedback 👍
@ajithkamath98243 жыл бұрын
Thanks for the short and informative video😊
@udaymadanu3 жыл бұрын
Best tutorial on CQRS!
@mrcarlpaton3 жыл бұрын
Thank you Jonathan, that was real simple to follow!
@jonowilliams263 жыл бұрын
Thank you ! Appreciate the positive feedback
@JoelBritos3 жыл бұрын
Great video, It helped me to finally understand how CQRS works
@jonowilliams263 жыл бұрын
Thanks ! Glad you like it 👍
@jadenrogers31332 жыл бұрын
Great video, clear and to the point. I like the way you structured it, the result / command / query are nested in the static class reducing the amount of custom dtos floating around which always felt off to me. Where to you come down on structuring the repository / unit of work. Generic repositories always felt "wrong" due to the discoverability issue that you mentioned. How does someone know IRepo actually works vs say uow.Todos.Add, uow.Orders.Find or ITodoRepo etc.
@dipjyotisikder35862 жыл бұрын
Thanks a lot jonathan. Its a great video! You saved too much of my time.
@maartenmateusen80573 жыл бұрын
Thnx for the video! Great stuff.
@jonowilliams263 жыл бұрын
Thank you !
@kj2w3 жыл бұрын
Loved this video. The statement of '...And what that means is just separating your reads from your rights (kzbin.info/www/bejne/o5Xddn59oa1jlbM)' is where the mental light bulb for CQRS FINALLY turned on for me. It did through me for a loop when I saw date of '30/12/2020'. I was thinking for a split second 'Hmmph, I guess Australia has 18 more months than here'.
@jonowilliams263 жыл бұрын
Thanks a lot ! Appreciate the positive feedback!
@nallaperumalthanthondri38172 жыл бұрын
Concise and nice tutorial
@sametcekiny3 жыл бұрын
The best and clear. Thank you!
@jonowilliams263 жыл бұрын
Glad it helped!
@psadlkfpsk3 жыл бұрын
Great introduction man, thanks a lot. Subbed!
@zengasiwingwa34083 жыл бұрын
Very well explained, keep it going!
@jaydeepvomexchandra3 жыл бұрын
Would have loved if you covered a sample unit test but it was a great tutorial.
@AjithKumarRS3 жыл бұрын
Such a good one. editing is awesome 😍.
@jonowilliams263 жыл бұрын
Thank you !
@jouchiwinchester26662 жыл бұрын
really enjoying your tuts, haha also the your voice is like dean winchester hahaha
@emnclm2983 жыл бұрын
Awesome tutorial Mate! Mind you do a video how to unit test cqrs/mediator pattern?
@jonowilliams263 жыл бұрын
Thanks for the positive feedback ! I really appreciate it ! I will add it to my backlog. But I have had multiple requests for it so might come out sooner rather than later 👍
@marshallnyamadzawo85533 жыл бұрын
Wow...this is too juicy. Thank you!!
@rojovel3 жыл бұрын
Fist of all great video!!! Just some observation about CQRS. I don't see a real benefit if we use a well coded services layer. Maybe it's something I'm missing about the CQRS whole idea.
@jonowilliams263 жыл бұрын
Thanks ! Appreciate the positive feedback! I think the best way I have heard it described is “putting developers into the pit of success.” So using this will help align all developers in the team to follow the request, handler and response pattern. And no doubt you can do the same thing without MediatR and get the same benefits of CQRS (single responsibility and independently evolving) but it will require a well documented coding standard so everyone is on the same page. Hope this helps 👍
@shaikzuhair85372 жыл бұрын
Great explanation
@jomarcordero45153 жыл бұрын
Excellent explanation thanks! Just missed to await the LINQ query with the async extension methods like: FirstOrDefaultAsync() , AddAsync(), etc... var todo = await repository.Todos.FirstOrDefaultAsync(x => ...); otherwise it will work synchronously.
@ivanmiroshnichenko42992 жыл бұрын
As my hobby, I've been getting the hang of English accents. You have an interesting one. What is part of the world you're from? My guess is south of the UK? But I'm a noob at that. I'm sorry if it was awkward of me :|
@AbPSlayer3673 жыл бұрын
Very interesting in using static class as wrapper around a single responsibility handler, command/query and responses instead of separate classes. Did you find any downstream impacts with this approach?
@jonowilliams263 жыл бұрын
Nah I haven’t found any negatives. As someone pointed out though you can do the same thing with namespaces. So I would choose either
@priyankubiswas96343 жыл бұрын
jonah rocks ... can you create a series on clean architecture
@ogkisel34313 жыл бұрын
Thanks for the video Jonathan. One thing is unclear: why should a container class be static?
@roybradley33173 жыл бұрын
When will the Authentication video be available. I've really enjoyed the CQRS series.
@impeRAtoR281616212 жыл бұрын
Creating multiple classes to get something from database is probably overkill for most but huge enterprise applications where work tons of developers
@HamzaKhan-fl8fp2 жыл бұрын
Hi Johnathan it's is very informative video but I have a question that can we create cqrs files automatically ?
@RickGraner3 жыл бұрын
Great video JW ... I came across this b/c I was looking to implement this pattern in my current .NET 4.8 project which needs refactoring (fat controllers) but I didn't want to do a re-write in CORE. Do you know if this pattern would work? or do I need to implement CORE?
@jonowilliams263 жыл бұрын
Thanks ! I appreciate the positive feedback ! Yeah I think it will work in .NET Framework because I think MediatR is .NET Standard. Check out the docs to make sure though 👍
@tinypanther273 жыл бұрын
Wouldn't it be more appropriate for the static class to be just a namespace? All those classes could be in the same file. Im only trying to understand if I am missing something
@frotes3 жыл бұрын
I think the reason for the static class is so that you can write everything like XXXX.query or XXX.command. Otherwise you can name the query/command XXXQuery. It's nice to have a file per XXX grouping, as code lens can't navigate from the query/command to it's associated handler
@jonowilliams263 жыл бұрын
Hi Mohammed , exactly what Frotes said. You could definitely just add them to a name space rather having them be an internal class. The more important concept is grouping your query, handler and response together!
@tinypanther273 жыл бұрын
@@frotes I get now. But, the samething can be done with namespaces too. You can still use it as XXXX.Query where XXXX is the namespace. You just need to be sure to include the correct namespace in the client. But I guess it doesnt really matter, but avoiding the enclosing static type would make the intent a bit more clear to someone new thats reading the code
@Wfmike2 жыл бұрын
I would prefer to use namespace rather than static class but that's just me, good tut.
@JavierDombronsky3 жыл бұрын
Nice video! I just wonder how to add validation to query params using record. If you have a class you can use DataAnnotations like [Required] but with this approach I don't see how to do that. Any thoughts? Thanks!!
@LossL3ss2 жыл бұрын
Thats a really good question! If someone could answer this, it would be very helpfull
@LossL3ss2 жыл бұрын
After some researches I've found 2 ways (I didn't tried yet): 1 - Define your record like this: public record SomeRecord([property: Required] PropertyName); Or public record SomeRecord([Required] PropertyName); 2 - You can use FluentValidator in your Record properties
@burakisleyici3 жыл бұрын
Thanks for tricks 👍
@hector90793 жыл бұрын
Muy bueno 👍
@damientohin96432 жыл бұрын
I love this pattern, and I think it is awesome. But concretely, what advantages does it bring to my microservice ? isn't it just easy to separate the logic away from my controller actions instead of introducing a new dependency and complexity just for this pattern ?
@cnikolov3 жыл бұрын
The only downside I found following along , sometimes you would want to share view models and (youw would ideally have them in viewmodels folder. to share more predictably and to resolve the namespace). The other thing I noticed, if you call your records Response, it seems very strange when you are reading the code in the controller.
@christiankhalil6433 жыл бұрын
Whats the point of making the class static? The items inside it are always reachable since there arent for example any fields or properties, is it just to be explicit?
@bramburn2 жыл бұрын
hi Jonathan can you use this on a desktop application?
@TheMiamiVice272 жыл бұрын
Hello Jonathan! How would you aggregate 2 or more handlers into single action. Let's say we have an user entity and cars entity, as well as join table (N-N) between cars and users. And lets say an user has 3 different cars. Well if we want to delete user from our repo we need to remove those connections to cars as well. In such a way that we have an aggregate handler (DeleteUserFromSystem) which behind the scene calls 2 commands. "DeleteUsersCars" (which deletes records in join table) and after that deletes an user calling "DeleteUser" which deletes user from our repo. All that should be 1 atomic operation (1 DB transaction, if for some reason one of those commands fails, etc.. all should be rolled back to state before calling "DeleteUserFromSystem") How would you do that. Because this expamples are way too easy.
3 жыл бұрын
Nice setup. Which monitor are you using?
@jonowilliams263 жыл бұрын
Thanks ! Just a cheap Kogan 34inch ultra wide.
@paulkeating92592 жыл бұрын
Just out of curiosity is this not CQS you are describing ? I brought up that i had used this pattern in an interview and they told me that i was explaining CQS not CQRS but when i look up CQRS online this is the type of content I usually find
@DyuKrow3 жыл бұрын
nice video!
@jonowilliams263 жыл бұрын
Thanks
@MortezaDalil3 жыл бұрын
You are the best
@Unleash1323 жыл бұрын
what happens if you have a more complicated handler or a Command with lots of fields? That static container will be huge.. would you separate it to files then?
@jonowilliams263 жыл бұрын
I think if the file was getting too large I would look at using a folder which contains all the code for a particular command or query. But if it gets that large to begin with maybe it should be refactored into smaller bits
@Unleash1323 жыл бұрын
@@jonowilliams26 Great! Thank you for the response. That's what I'm doing right now. The handler isn't that big but the command itself has a lot of fields can't really separate it because that's how the request to the api is.
@jonowilliams263 жыл бұрын
Ahh yeah I get you now. Yeah you can’t really separate out a query if it has lots of fields. So go with the folder approach. The main idea is keep related items close by so devs don’t have to go searching for it
@codewithkashif2 жыл бұрын
I have a quick question i.e. why people use MediatR with CQRS only?
@redmizaki58383 жыл бұрын
I wonder if it's possible to do request validation with records, any idea plz?
@jonowilliams263 жыл бұрын
Yeah it is possible. Currently editing a video about it now 👍
@redmizaki58383 жыл бұрын
@@jonowilliams26 Ok fantastic. I look forward to it 🙂
@viniciusdavila27373 жыл бұрын
When should you definitely NOT use CQRS? Also how do you feel about the .NET Core job market? Growing demand? Just starting out.
@jonowilliams263 жыл бұрын
It really depends on the project. If I’m working on an API I am more than likely going to use CQRS because it follows the request / response pattern. But if I need to build a windows service for example using CQRS is probably the wrong choice. And I think investing in learning .NET core is a good choice because it’s a great framework and there is a lot of .NET jobs around.
@viniciusdavila27373 жыл бұрын
@@jonowilliams26 Thanks for the reply. Do you mind if I suggest a topic for your backlog? DDD
@Time213 жыл бұрын
Am i missing something because in the Controller you wrote new GetTodoById and the class is static. Is it possible to create instance of a static class using the new keyword?
@jonowilliams263 жыл бұрын
You’re not creating an instance of the static class GetTodoById, we are creating an instance of Query. Since the Query class is inside the static class, in order to create the query you have to write “new GetTodoById.Query()”
@Time213 жыл бұрын
@@jonowilliams26 isnt it the same like the Command static class Todo?
@jonowilliams263 жыл бұрын
Since the query and commands are internal classes they need to be referenced by using GetTodoById.
@Time213 жыл бұрын
@@jonowilliams26 Thank you for clarifying that.
@otobest16713 жыл бұрын
I can't understand this pattern. Should i write a class per a method ? It will be more complicated i think.
@sourabhsharma48783 жыл бұрын
Hope you are Ok. But why new vedios are not coming ?
@MrBa1433 жыл бұрын
Everyone keeps saying "You can split your reads and write into different databases", but i dont need CQRS to do that. I want CQRS to split up my dependencies across meaningful events, instead of gathering them all in one handler (controller etc). A result of this, is to inject a single repository (ReadRepository, WriteRepository) into my handler. I dont see anything wrong with further dividing your repository pattern, into a IReadRepository and IWriteRepository and use them both in different controllers. Thus i dont understand how CQRS provides this functionality. Can someone give me the missing piece please.
@jonowilliams263 жыл бұрын
CQRS isn’t a framework. It’s a design pattern. You need to implement the design pattern as you see fit. There is nothing stoping you from having your reads use a ReadRepository and your writes use a WriteRepository.
@MrBa1433 жыл бұрын
@@jonowilliams26 Yeeeeah i kind of missed the part where the CQRS pattern and the MediatR library are not mutually exclusive, thus i mixed them together.
@williamprogramer41682 жыл бұрын
⭐⭐⭐⭐⭐
@cmtv3573 жыл бұрын
Why use a repository?
@humanbot52473 жыл бұрын
but why so fast...thanks
@jpboy19623 жыл бұрын
Its a bad idea the put the handler in the same file as the request. It increases the coupling between them and loose coupling is one of the biggest advantages of MediatR. You could have multiple handers for any given request.
@davidlester66733 жыл бұрын
Why do people separate classes and call it CQRS!!!! CQRS is about separating reads and writes at the database. What you are doing is implementing the mediator pattern.
@vamteusz38983 жыл бұрын
Command shouldn't return value
@jonowilliams263 жыл бұрын
Please explain how you return the ID of a newly created item without returning a value from commands?
@vamteusz38983 жыл бұрын
@@jonowilliams26 e.g. you can generate guid in controller and pass it to the command
@jonowilliams263 жыл бұрын
@@vamteusz3898 going to have to disagree with that one. I don’t think the API layer should be providing the IDs when in most cases IDs are auto-incrementing generated by the database.
@vamteusz38983 жыл бұрын
@@jonowilliams26 you can generate guid even on the front side but the rule that command shouldn't return value is a primary rule in cqrs (and the most often broken i think)