Extremely FAST Caching Repository With Decorator Pattern in ASP.NET Core

  Рет қаралды 54,351

Milan Jovanović

Milan Jovanović

Күн бұрын

Пікірлер: 224
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Want to master Clean Architecture? Go here: bit.ly/3PupkOJ Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
@filipeencarnacao2840
@filipeencarnacao2840 2 жыл бұрын
I already knew this pattern, because of Steve Ardalis, and let me tell you, i used this in a software project, from the company i work at, and it didn't cost almost any time, simply fantastic
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Excellent pattern indeed. And you can keep reusing it all over the place.
@Jbobonline
@Jbobonline 2 жыл бұрын
Thanks Milan, Please keep in mind that using a DISTRIBUTED cache is required in order for your service to be scalable. Otherwise, different instances of the same service will not be aware of each other’s in memory cache. Great video!
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Of course, if you have multiple services running then you need a distributed cache.
@musacj
@musacj Жыл бұрын
Milan, I like the way your videos have detail and they're not too long either. The simplicity of your explanations have made me want to implement most of things you explain on your videos. Your presentations aren't too fast and not too slow, so it makes it easy to understand. Thank you for your time
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Thank you for watching them! 😊
@PelFox
@PelFox 2 жыл бұрын
I use the same pattern, its great. One thing I like to add is to have any Update/Delete method to clear (or update) the cache.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Smart!
@kharade123
@kharade123 2 жыл бұрын
this is what I was looking for
@DanGahagan
@DanGahagan 2 жыл бұрын
I was looking for that as well. Would be a nice topic for a future video
@nickolaki
@nickolaki 2 жыл бұрын
How would you implement that ? Would love to know
@michaelswells
@michaelswells 2 жыл бұрын
@@nickolaki We usually do a try get, if it exists, we remove from cache and then add it back in with the updated values. We do not do physical deletes. We mark the record as deleted.
@markovuckovic9430
@markovuckovic9430 2 жыл бұрын
This is amazing... Even though I use different tech stack in my projects, the concept of implementing cache with decorator pattern is something that I'm willing to try out as soon as there's an opportunity for that...
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
There are many other use cases for Decorators, such as: logging, validation, resource-based authorization...
@radeksendecki9922
@radeksendecki9922 2 жыл бұрын
Great work. As always clearly presented in the simplest form, but covering the essence of the subject.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Thanks a lot, Radek 😁
@tedchirvasiu
@tedchirvasiu 2 жыл бұрын
That Scrutor implementation seems more flexible which is really cool.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
I really like it also, easy to write when you have a lot of dependencies
@tedchirvasiu
@tedchirvasiu 2 жыл бұрын
@@MilanJovanovicTech Thank you for showing it
@ALOKSHARMAMD
@ALOKSHARMAMD 2 ай бұрын
i have used this implementation in conjunction with Faster hybrid cache, and works fantastic for my system. we implemented this a few years ago and never had to look back.
@MilanJovanovicTech
@MilanJovanovicTech 2 ай бұрын
You're using HybridCache from preview?
@ALOKSHARMAMD
@ALOKSHARMAMD 2 ай бұрын
@@MilanJovanovicTech no not that, the one called Microsoft.Faster, it have hybrid caching in sense that it provides both in-memory and persistent disk cache to go beyond memory cap[acity. i have built my layer on top of this library. btw i tried commenting with git link for library but my comment was not posted.
@milicabozic9897
@milicabozic9897 2 жыл бұрын
Awesome video, I really like the way you explain things 😊
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Thank you, Milica. I'm glad you found the video useful 😁
@samuelterrazas3191
@samuelterrazas3191 7 ай бұрын
I always watch your videos. They've really helped me a lot in growing professionally in my job. Honestly, I would pay to watch your videos with subtitles correctly translated into Spanish instead of the automatic KZbin ones that often don't work well or translate incorrectly.
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
That one's gonna be tricky 😅
@kydlnw2023
@kydlnw2023 2 жыл бұрын
I was really thinking about doing something like this but had no idea how to do it(1st year on software dev uni so don't know quite a lot). Thanks for the video.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Pretty cool, I'm glad you ran into this video then 😁
@andersjuul8310
@andersjuul8310 9 ай бұрын
I thought I'd seen you make a video on this -- and just what I needed. Brilliant, to the point as always. Thanks!
@MilanJovanovicTech
@MilanJovanovicTech 9 ай бұрын
Glad it was helpful!
@adiazwise
@adiazwise Жыл бұрын
Thanks, Milan , excellent implementation of the decorator pattern.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Awesome, glad you found it useful 😁
@camilotorresc.2046
@camilotorresc.2046 2 жыл бұрын
Fantastic video, well explained. I have used Scrutor and the way that works is so good because under the hood it uses the built-in ASP .NET Core DI container. I guess that caching behavior can also be done using the new Output caching middleware built-in .NET 7. Great video!
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
It's an entirely different type of caching, so we should be careful. I think it's more appropriate for caching HTML output.
@sergiom.954
@sergiom.954 2 жыл бұрын
Very clean design for caching queries on repositories. I already have in mind a few queries of my project to implement the pattern this way. Thanks Milan!
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Awesome Sergio, glad you can apply this to your project 😁
@colinwiseman
@colinwiseman 2 жыл бұрын
Although I know I'll never change my repo or my cache layer, I really get old grumpy and I would merge the cache code into the repo. but that decorator DI stuff just makes it clean! This old dog may have learned a new trick 👍
@colinwiseman
@colinwiseman 2 жыл бұрын
But question : why add Scrutor when you had it working already? Adding third party for no extra benefit doesn't seem smart.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Just wanted to show multiple options, by introducing Scrutor. In general, I would use Scrutor by default since it's more feature rich.
@colinwiseman
@colinwiseman 2 жыл бұрын
@@MilanJovanovicTech fair, if you use many of the features. My fear for many a bit of software out there is over engineering, especially if it someone building a website for their local coffee shop 🤣 I've seen too many examples of Financial Institution grade coding running on websites that make them so complicated that the next Dev along can't fix it 🤣 that's why I always question additions for the sake of additions. But that Decorator pattern with DI... That's a worthy addition.
@ahmadsabbagh1554
@ahmadsabbagh1554 2 жыл бұрын
Great work. Keep going 😍🥰
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Thank you so much! 😊
@EmptyGlass99
@EmptyGlass99 2 жыл бұрын
Very clean and useful presentation.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Thanks, I'm glad you liked it 😁
@miodragsimunovic5851
@miodragsimunovic5851 2 жыл бұрын
Neat and tidy ! It's great you have shown few ways for service registration.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Which did you like the most?
@miodragsimunovic5851
@miodragsimunovic5851 2 жыл бұрын
@@MilanJovanovicTech Hi Milan. The second one is the most detailed and lets you customize it a bit more. The Scrutor is fine, but leads you to dependency on 3rd party library fortunately one which can go along with other DI containers. Great job !
@daedwill
@daedwill 2 жыл бұрын
Very clear explanation, thank you!
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Awesome, I'm glad you liked it! 💯
@yunietpiloto4425
@yunietpiloto4425 2 жыл бұрын
Really nice stuff man, well explained, well presented...quality content, keep it up!
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Thank you so much! 😁
@krzysztofhandzlik9273
@krzysztofhandzlik9273 Жыл бұрын
Great video ! However it would be worth mentioning, that we should keep in mind some cache invalidation strategy. Thanks for Your work :)
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Definitely, I kind of failed to cover that aspect properly. I'll make it right in a future video
@beirinhaaa
@beirinhaaa Жыл бұрын
Very Nice explanation!!!! TKS for show many ways to do that!
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
You are welcome!
@lucek15951
@lucek15951 2 жыл бұрын
Found your channel a few days ago. You are doing a magnificent job. The implementation details, like the options for registering services in DI, are fantastic!
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Thanks a lot, Kamil! I'm glad you liked it 😁
@shanemonck783
@shanemonck783 2 жыл бұрын
Awesome loving your videos! so happy I stumbled upon your page
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Thanks a lot Shane, I'm glad you're loving the content 😊
@krccmsitp2884
@krccmsitp2884 Жыл бұрын
Well done, comprehensive and straighforward as always in your videos. Besides, one should consider using ValueTask instead of Task in such cases.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Why do you think a ValueTask is a good fit there? 🤔
@krccmsitp2884
@krccmsitp2884 Жыл бұрын
A ValueTask is more lightweight, with less memory usage since it's a struct, and doesn't create an actual Task when it is already completed when awaited--which is mostly the case in this use case of caching.
@androidsavior
@androidsavior 7 ай бұрын
Is it a best practice to always a have a repo and a cached version of the that repo or we can integrate the caching inside the one single repo ?
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
You're welcome to just have caching in the repo
@ugurcan4638
@ugurcan4638 11 ай бұрын
So helpful video series. Thank you. I want to ask what is the shortcut keys at min 6:43 (navigating to Program.cs).
@MilanJovanovicTech
@MilanJovanovicTech 11 ай бұрын
Ctrl + T?
@ugurcan4638
@ugurcan4638 11 ай бұрын
Thanks a lot@@MilanJovanovicTech
@LindenMikus
@LindenMikus 2 жыл бұрын
I think for unit testing the scutor approach is the nicest to work with because you are dealing with an interface instead of direct class
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Agreed, plays very nice with unit testing
@pedroferreira9234
@pedroferreira9234 2 жыл бұрын
You can still use the interface with addScoped I think you just need to use the provider services.AddScoped(); services.AddScoped(provider => new ServiceCache(provider.GetRequiredService()) ); where the Service : IService
@eddypartey1075
@eddypartey1075 Жыл бұрын
Milan, I'm not that experienced but why don't you use async/await in CachedMemberRepository?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Returning a Task is enough
@rezameshksar503
@rezameshksar503 Жыл бұрын
Great presentation as always. What is the best practice and approach to conditionally use cached data? For example, can the API look at cache header in the request, and decide which repository to use? How does the DI configuration work in this case? Maybe a repository factory class?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
You can inject the HttpContext which should have the headers present perhaps, and check if you should use cache or not
@codewithkashif
@codewithkashif Ай бұрын
Great video, simple and pragmatic too! My only question is in decorator patten conventionally existing class will remain as is and new wrapper class behaves as decorator. this means in this case CachedMemberRepository class should act like decorator. kindly let me know your thoughts
@MilanJovanovicTech
@MilanJovanovicTech Ай бұрын
Yes
@codewithkashif
@codewithkashif Ай бұрын
@@MilanJovanovicTech so in your example you have used it vice versa so is this decorator pattern too?
@volodymyrliashenko1024
@volodymyrliashenko1024 2 жыл бұрын
Thanks Milan! I need to try using Scrutor library. But do you know how to create decorator dynamic/on fly? I was able successfully do that with Castle library and IInterceptor interface, but having issues during the debug. So, I'm thinking the better solution would be having the Source Generator which would create a decorator for me. Did you try to do something like that?
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
I didn't need to do something like this before
@taner-saydam
@taner-saydam Жыл бұрын
An ingenious way, thanks🤩🤩
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Glad you like it!
@taner-saydam
@taner-saydam Жыл бұрын
​@@MilanJovanovicTech I live you all videos. Thanks a lot. Really ☺
@NAEL4SLR
@NAEL4SLR Жыл бұрын
Awesome contents! Thanks for sharing
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Thanks for watching!
@vAmp1que
@vAmp1que 2 жыл бұрын
Milan, appreciate for your time! We are gonna set the cached entry every time when we decided to update the entity, isn't it? So how to do it better? Is it better rather than using only EF or it depends on situation. For instance, in project where we changing entities rare it may be huge performance upgrade, but in the opposite situation we could get some performance degradation imho. What's your opinion at this point? Thx.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
I think that updating the cache when you update the Entity is a viable option. We can usually live with a short stale cache.
@vAmp1que
@vAmp1que 2 жыл бұрын
@@MilanJovanovicTech thx man. And thx KZbin algorithm for recommendation. Really enjoy your content. Hope your channel will growth up even faster than 233x;)
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
@@vAmp1que I hope so to 🍀
@monsieurnet
@monsieurnet Жыл бұрын
I wonder if it's really usefull to use Decorator pattern on a repository for this purpose. Because you have to create a new class for all the repositories you want to cache the data. Creating a generic repository with cache feature is maybe easier to handle on long time perspective even it's not a SOLID principle ? I would like to know your advise.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Too much generic will constrain your design, so tread lightly
@monsieurnet
@monsieurnet Жыл бұрын
@@MilanJovanovicTech Thank you for your answer. I will take it in mind for my next development
@ezecel9
@ezecel9 2 жыл бұрын
Thanks! If instead of an id I want to filter by many conditions (for example, Page, PageSize, MemberName, memberDate, etc), do I have to concatenate them in the key? Or maybe make a hash with the sql generated by EF? Which is the best approach? Thanks!
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Yes, you need to include anything that can change in the cache-key
@abdelrahmanmahmoud2285
@abdelrahmanmahmoud2285 Жыл бұрын
Awesome video , keep going
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Thank you!
@hmsiegel79
@hmsiegel79 Жыл бұрын
Hi Milan, I noticed something while going through the video. I was having trouble getting the caching to work and was getting a circular reference error when starting the application. I then noticed that you added "build.Services.AddMemoryCache();" after running the application the first or second time. Just an FYI if others have the same issue.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Thanks for pointing that out!
@xantari79
@xantari79 7 ай бұрын
I see you using a lot of keyboard shortcuts to auto complete things. Perhaps it would be a good idea to show those in a tips and tricks video?
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Maybe, but it's just a few basic shortcuts
@TheAproeX
@TheAproeX 2 жыл бұрын
What is the best time for the cache to expire? How should we calculate this, what should the decision be based on? I know that cache invalidation is a complex topic, but perhaps there is a simple way to determine this?
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
It depends on the load on your application, really. And how long the value can be valid in the cache. The longer you can cache, the better. I usually use 5-10min for values that can change from time to time.
@TheAproeX
@TheAproeX 2 жыл бұрын
@@MilanJovanovicTech Thanks for the answer. Btw. what keyboard do you use?
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
@@TheAproeX Nothing fancy: Logitech K120 Gets the job done 😁
@pazzuto
@pazzuto 2 жыл бұрын
Since the decorator class adds additional functionality to the repository, I normally add code to clear (invalidate) the cache when one of the other methods are called (UD) in the decorator class; that way I don't have to guess how long to cache.
@sameerpanicker7452
@sameerpanicker7452 5 ай бұрын
Milan, if we have multiple service classes or repos and we need to implement caching on all of them, should we create separate decorator classes for every service class ? Is that the correct way of doing it ? Could you please suggest any good practice?
@MilanJovanovicTech
@MilanJovanovicTech 5 ай бұрын
That's what you'd end up with... Perhaps there's some clever way to implement this with attributes.
@sameerpanicker7452
@sameerpanicker7452 5 ай бұрын
Thank you Milan for the suggestion. I will have a look.
@thegaribovv
@thegaribovv 7 ай бұрын
I have some methods which accept Expression as argument, How can I generate cache key for this expression? Generally should we cache expression based methods result?
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
It would be smart to pass in the cache key as an additional argument
@thegaribovv
@thegaribovv 7 ай бұрын
@@MilanJovanovicTech Then it will broke the repository pattern
@DavidGagne
@DavidGagne 2 жыл бұрын
This is very interesting, thank you for your videos! I would assume that MemberRepository is for read purpose only? Because I use the repository pattern for writes, and I don't think caching entity would work.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Why wouldn't it work? Because EF wouldn't track it? We can fix that easily with Attach.
@DavidGagne
@DavidGagne 2 жыл бұрын
@@MilanJovanovicTech Ok yes it should work with Attach! Thanks
@salmanzafar-jr1iu
@salmanzafar-jr1iu Жыл бұрын
Don't you think it's a proxy pattern I just got confused :) can you clarify as per my understanding The proxy pattern adds a layer of indirection to the object that it is wrapping. The client interacts with the proxy, which in turn delegates requests to the wrapped object. This can be used to add additional functionality to the wrapped object, such as caching, lazy loading, or security checks. The decorator pattern, on the other hand, adds new behavior to an object by wrapping it with a decorator object that contains the new behavior. The decorator object implements the same interface as the wrapped object, and forwards requests to the wrapped object. This allows you to add new behavior to an object without changing its implementation.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Yeah, it does seem that this is the "Proxy" pattern after much comments on this video.
@davidwilliss5555
@davidwilliss5555 10 ай бұрын
Nice, but in your update method on the decorator class, you should modify the Update function to at least invalidate the cached instance if it's already in the cache or the next get will get the old value instead of the new one.
@MilanJovanovicTech
@MilanJovanovicTech 10 ай бұрын
Good suggestion
@loam
@loam 2 жыл бұрын
I guess, when updating the entry (which is Member in this case), cache also should be updated. Is it so?
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Indeed, that should be the case. Or rather - we can just clear the cache, and let the next query fill it.
@loam
@loam 2 жыл бұрын
@@MilanJovanovicTech Thanks for the reply 🙏👌
@GeoffSeeley
@GeoffSeeley Жыл бұрын
This assumes your API is the only source of change in the database. If that is not the case, you risk stale data in the memory cache before it expires so that is something to be aware of.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Of course, this is just one piece of the puzzle.
@agustinmolina5170
@agustinmolina5170 9 ай бұрын
i give you like from start because i see you like Warcraft!!
@MilanJovanovicTech
@MilanJovanovicTech 9 ай бұрын
Haha, used to play a lot back in the day 😁
@feitoza.system
@feitoza.system Жыл бұрын
I like to read, but it's kinda too theoretical. You make this feel so practical and real in the daily development, I'm following you to learn everything I can about good practices and performative code
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Awesome, I'm so happy you found this video helpfuln
@markus27183
@markus27183 Жыл бұрын
caching is about as practical as you get
@balajisairamnarasimhan
@balajisairamnarasimhan Жыл бұрын
Mostly recommended cache is distributed cache like redis , mongodb etc rather than mem cache
@balajisairamnarasimhan
@balajisairamnarasimhan Жыл бұрын
If the use case is simple , then it makes sense to have this memcache 😊
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
You won't need it in a non-distributed system
@shabtaiben-david8173
@shabtaiben-david8173 7 ай бұрын
what about the case I need to refresh specific id data, i.e. ignore cached instance?
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
kzbin.info/www/bejne/j5Wok3draMhreNU
@shabtaiben-david8173
@shabtaiben-david8173 7 ай бұрын
@@MilanJovanovicTech Thank you, actually I mean how to integrate it into GetOrCreate mechanism (not rabbitMQ in my case). I just thought about passing 'bool suppressCache' argument to the CRUD operations...
@balsastevovic9225
@balsastevovic9225 2 жыл бұрын
What if you add a new member, and then after you call the GetAll in the CachceRepository? Its not gonna have the newly added member?
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Invalidate the cache after adding a member
@balsastevovic9225
@balsastevovic9225 2 жыл бұрын
@@MilanJovanovicTech Thank you!
@andersjuul8310
@andersjuul8310 9 ай бұрын
Say, if organized in a clean architecture, where would you think the decorated class should be? To me it's kinda a technical concern not appropriate for Domain. Where then? :)
@MilanJovanovicTech
@MilanJovanovicTech 9 ай бұрын
A decorator of what? If it's a decorator solving technical concerns, then it's probably more appropriate to place it in Infrastructure
@andersjuul8310
@andersjuul8310 9 ай бұрын
In my case it is decorating a Domain Service -- but the caching itself seems like a technical concern. Infrastructure-for-caching does seem appropriate. Thanks again!
@vincenthamelin6115
@vincenthamelin6115 10 ай бұрын
Would it be possible to update the video (or make a different one) where you show how you would implement invalidating the cache when inserting, updating and deleting. Thanks
@MilanJovanovicTech
@MilanJovanovicTech 10 ай бұрын
kzbin.info/www/bejne/j5Wok3draMhreNU
@donatolucente1209
@donatolucente1209 2 жыл бұрын
What abount entry invalidation? how do you implement it with this approach?
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Simplest would be straight in the CachedMemberRepository. Decorate the other methods the make changes, mainly Update, and invalidate the cache.
@donatolucente1209
@donatolucente1209 2 жыл бұрын
@@MilanJovanovicTech Thanks!
@vivekkaushik9508
@vivekkaushik9508 2 жыл бұрын
Brilliant.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Thank you very much! 😁
@amitsinghrawat4760
@amitsinghrawat4760 2 жыл бұрын
Hi Milan, Requesting video on Concurrency token and Handling Concurrency Conflicts by using EF core.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
All right Amit, I added it to my production list 😁
@ahmedanwer1767
@ahmedanwer1767 Жыл бұрын
Awesome
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Thanks!
@sandorvarga7437
@sandorvarga7437 2 жыл бұрын
Success.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
💯
@chriscardoz
@chriscardoz 2 жыл бұрын
Castle proxy ? Any drawbacks ?
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Haven't used it, so I wouldn't know
@UsmanKhalidTV
@UsmanKhalidTV 2 жыл бұрын
Very clean code. Can you please also upload your code to github repository.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
I share the code with my Patreon supporters. But there are some examples available on my GitHu that you can look at :)
@jamesattwood6809
@jamesattwood6809 2 жыл бұрын
Great video thank you. I am looking at making a GenericRepository (Using Generics) to handle basic CRUD functionality with EF Core to handle various entity types via T. I would like to also have a GenericCaching repository as well based on this repository. I have existing service classes doing this work currently that I am now able to offload to the main generics repo by inheriting the GenericRepository base class and passing in the entity type. Since my endpoints are injecting the service class for a given entity type (because each service class also has additional methods) I am struggling to figure out the chain of inheritance here and how I can make a call to the service class and have it route correctly between cached and non-cached . I suspect it would be a different design pattern... Currently I am using your DI mapping technique to map between the cached and non-cached service classes. Each of these classes inherits from the cahced and non-cached base classes. This is working, however I am not sure if this is best practice/ or the most elegant solution. Any thoughts appreciated!
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
With the Decorator pattern as I showed it here, you can't really control which method you are calling (cached/non-cached). You would need to think of something else. Or create two separate services perhaps? Inject both, and decide which to call?
@jamesattwood6809
@jamesattwood6809 2 жыл бұрын
@@MilanJovanovicTech I Need to think this one through clearly. Appreciate your thoughts on this!
@majormartintibor
@majormartintibor 2 жыл бұрын
Milan pls consider to make a discord server. Would be awesome.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Good idea Martin. I'm definitely going to do it at some point.
@ryanalafountain
@ryanalafountain Жыл бұрын
How do you add the cached member to change tracking?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
dbContext.Attach(member)
@ryanalafountain
@ryanalafountain Жыл бұрын
@@MilanJovanovicTech so I would just inject the context into the decorator as well? Would it make more sense to implement the cache in the repository instead of decorating in that case then?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
@@ryanalafountain I think you can handle attaching in the decorator also, along with the caching. So you just inject the context into the decorator, resolve from cache, and attach.
@kenjiobara
@kenjiobara 2 жыл бұрын
how to generate construct using the new sugar syntax?
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
What did you mean to say here?
@jeetsingh4588
@jeetsingh4588 6 ай бұрын
what if your generic repository have predicate/func type parameter, how you will make a cache key unique in that case?
@MilanJovanovicTech
@MilanJovanovicTech 6 ай бұрын
Pass the cache key as another argument
2 жыл бұрын
Decorator pattern is really nice, but there is a lot of boilerplate. It would be nice to see a SourceGenerator for this pattern.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
How will you control cache time, cache eviction, keys?
2 жыл бұрын
​@@MilanJovanovicTech Might be done with Attributes etc., however. It would probably not be the cleanest, as .Net does not support TimeSpan etc. on Attributes ("00:00:00.000" strings instead?). Writing the class partially is also an option, but not easy to say. Next time I use this pattern (maybe 3 years since last time), I would definitely look into creating my own generator, if it does not exist then. And well, If I need to create a short generator, then I could just predefine some of the rules in the generator myself also I guess. Have to say, have used both generated (IL.Emit) proxies and Fody for similar issues before. But that seems like overkill at this time.
@InshuMussu
@InshuMussu 10 ай бұрын
i am a fan of you ❤
@MilanJovanovicTech
@MilanJovanovicTech 10 ай бұрын
Thank you! :)
@andresbeltran5779
@andresbeltran5779 4 ай бұрын
Excellent
@MilanJovanovicTech
@MilanJovanovicTech 4 ай бұрын
Thanks!
@nasih6474
@nasih6474 11 ай бұрын
Can i get this source code if i join the patreon?
@MilanJovanovicTech
@MilanJovanovicTech 11 ай бұрын
Yes, that's the whole point :)
@guillermovalenzuela9509
@guillermovalenzuela9509 2 жыл бұрын
Talking about decorator pattern, why you dont use a base decorator class , every concrete decorator must implements base decorator instead the concrete component
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
What would be the benefit of that approach?
@guillermovalenzuela9509
@guillermovalenzuela9509 Жыл бұрын
@@MilanJovanovicTech more than a benefit, I want to understand because the classical pattern defines four steps : a component, concrete component, a base decorator class and some concretes decorators
@utubewebbes
@utubewebbes 2 жыл бұрын
This is not the decorator pattern. It's the proxy pattern. A decorator decorates an existing class with new functionality. E.g. you have a Shape class that contains information about its dimensions and you would like to add a Paint method to that class in order to render it on a canvas. You use a decorator to add that completely new functionality. The proxy pattern allows you to replace any reference to a specific type of interface to an instance of the proxy and the proxy will do something with requests before it will proxy the request to the instance being proxied. Proxies are useful for adding logging, adding event triggers, encoding/decoding (SSL offloading) or... caching. You probably will have heard of network proxy servers.... that are most often used for SSL offloading and caching.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
It's still not as clear to me. And I've read a lot about Decorator vs Proxy after posting the video. By some definitions, this is a Proxy indeed. By others, I can designate it as a Decorator. The line between them is very fuzzy.
@utubewebbes
@utubewebbes 2 жыл бұрын
@@MilanJovanovicTech The reason line seems blurry (but it isn't once you know) is that a decorator should also act as a proxy. The existing methods of the class being decorated should also be present on your decorator and for those methods, the decorator acts as a proxy by simple passing the request down to the class it decorates.
@serb1146
@serb1146 Жыл бұрын
Both patterns are wrappers. Both based on composition principle. But diff is that proxy manages life cycle of its "proxied" object itself, instead decorators composition controlled by client code. Therefore, in this case, client code decided "game rules". This is more decorator than proxy IMHO. Thank you for video/idea, Milan, keep been so informative!
@Bennevisie
@Bennevisie Жыл бұрын
Semantics. Big question is: “Does it achieve the desires outcome?”
@eobardthawne6903
@eobardthawne6903 8 ай бұрын
Thanks for pointing this out. I was thinking the same.
@empireofhearts
@empireofhearts 7 ай бұрын
how would you handle cachetimes being stored in config or somewhere and are different for each method and need to be passed when method is called? i guess for sake of simplicity you hardcoded value here but i think that wont be true
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Options pattern, and load the values when app starts
@empireofhearts
@empireofhearts 7 ай бұрын
@@MilanJovanovicTech agreed. My question is geared towards the same interface used in both actual and cache class is not valid at that time as the contract for cache class requires cache time as param in the method
@markus27183
@markus27183 Жыл бұрын
This is neat, but in the GoF pattern, the object has a reference/pointer to its own interface, rather than to a class which implements the interface. Also this decorator pattern has nothing to do with making the caching itself fast.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
No, it has to do with making the repository fast using caching
@pochtaliot
@pochtaliot 2 жыл бұрын
Well, I always thought that introducing classes such as CachedMemberRepository is a Proxy pattern
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Call it what you like, but we're on the same page when it comes to the implementation. Right?
@pochtaliot
@pochtaliot 2 жыл бұрын
@@MilanJovanovicTech if we call things whatever we like it's not a learning but exchanging of thoughts, right? And a good teacher is able to accept his mistakes, isn't he? What you've shown it's a proxy pattern not decorator as it was announced in title.
@pochtaliot
@pochtaliot 2 жыл бұрын
@@MilanJovanovicTech sorry if it looked like offending. I jus wanted to clarify
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
@@pochtaliot I researched this little, and I'm still of the opinion that what I showed is a Decorator. "Decorators are additive; meaning they only add new functionality by wrapping the function call and returning the original value. It can however do anything before or after that call. You can for example log every value when a function is called or dispatch an event. Just make sure to return the original value. Proxies are restrictive; meaning they can change the behavior of a function or even restrict calling a specific function by throwing an exception." Source: doeken.org/blog/decorator-vs-proxy-pattern
@pochtaliot
@pochtaliot 2 жыл бұрын
@@MilanJovanovicTech may be. But you need to check the uml structure too. And the proxy pattern's uml is fully regards to your code.
@vipuldimri6571
@vipuldimri6571 Жыл бұрын
How to update or reset the cache if we update the customer ? Inside update , delete customer handler I am doing like this . await _repositoryManager.Save(); if (_repositoryManager.CustomerRepository is ICacheableRepository cacheableRepository) await cacheableRepository.ResetCache(string.Format(Customer.CacheKey, customer.Id));
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Video on that coming out in a week 😅
@murat.yuceer
@murat.yuceer 2 жыл бұрын
I prefer aspect oriented technique to cache
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Why do you like that approach?
@LimitedWard
@LimitedWard 2 жыл бұрын
The only downside I see with this approach is the use of the concrete implementation of MemberRepository in your CachedMemberRepository. Won't that make it harder to unit test the CachedMemberRepository since you can't inject a mock implementation?
@loam
@loam 2 жыл бұрын
Hm, what if injecting IMemberRepository interface object to the decorator? Also, as far as I remeber, with ASP.Net DI container one can pass lambda directly to specify how the class will be instantiated.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Indeed, that's a good point. Later on in the video you can see I switched to IMemberRepository.
@eduardoyupanqui
@eduardoyupanqui 2 жыл бұрын
We need to depend on abstractions, not implementations. Why not? public class CacheMemberRepository : IMemberRepository { private readonly IMemberRepository _memberRepository; public CacheMemberRepository (IMemberRepository memberRepository){} } public class MemberRepository : IMemberRepository { }
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
That's the implementation in the end
@Real-Hindu-Us88
@Real-Hindu-Us88 Жыл бұрын
Video is not clear
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
You could at least explain why
@eobardthawne6903
@eobardthawne6903 8 ай бұрын
You are creating a Proxy pattern and not a decorator. Decorators work similar to how attributes extend functionality of existing action methods or controllers. In this example, you are creating a class which extends an existing class and adds new functionality, which is NOT a Decorator but a wrapper or proxy.
@MilanJovanovicTech
@MilanJovanovicTech 8 ай бұрын
The majority of devs, including myself, know this as a decorator. Popular DI libraries implement this as a decorator and not a proxy. Call it what you wish, I'm not saying it's wrong. In fact, I only learned about the proxy pattern when publishing this video a year or so ago.
@AsadujjamanShohan
@AsadujjamanShohan Жыл бұрын
Thanks for your explenation, I am facing a problem when I am trying to register open generic class using decorate. This is the error I am getting. "Could not find any registered services for type". Not sure is it bug or my mistake. Here is my code. builder.Services.AddScoped(typeof(IMemberRepository), typeof(MemberRepository)); builder.Services.Decorate(typeof(IMemberRepository), typeof(CachedMemberRepository)); Do you have any idea why it's not working?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Why is MemberRepository generic though? 🤔
@AsadujjamanShohan
@AsadujjamanShohan Жыл бұрын
Yes your are right IMemberRepo and MemberRepo should not be generic. Actually I wanted to follow a generic repository pattern to make that dynamic. This is the actual code looks like. builder.Services.AddScoped(typeof(IGenericRepository), typeof(GenericRepository)); builder.Services.Decorate(typeof(IGenericRepository), typeof(CachedMemberRepository)); the error is occuring from 2nd line "Could not find any registered services for type IGenericRepository"
@robslaney3729
@robslaney3729 2 жыл бұрын
Consider GetRequiredService instead of using "!" to suffice nullability
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Great tip! Thank you!
@marwabenissa8955
@marwabenissa8955 Жыл бұрын
how can I do that ?
@robslaney3729
@robslaney3729 Жыл бұрын
@@marwabenissa8955 GetRequiredService() is an extension method that throws if the requested "service" cannot be satisfied. That way, if can never return the default of "T"
How To Use The Specification Design Pattern With EF Core 6
19:13
Milan Jovanović
Рет қаралды 40 М.
Machine Learning for Everybody - Full Course
3:53:53
freeCodeCamp.org
Рет қаралды 7 МЛН
Não sabe esconder Comida
00:20
DUDU e CAROL
Рет қаралды 64 МЛН
Wait… Maxim, did you just eat 8 BURGERS?!🍔😳| Free Fire Official
00:13
Garena Free Fire Global
Рет қаралды 8 МЛН
CAN YOU DO THIS ?
00:23
STORROR
Рет қаралды 47 МЛН
Coding Shorts: Response Caching in ASP.NET Core
11:33
Shawn Wildermuth
Рет қаралды 7 М.
Blazing Fast Caching Service In ASP.NET Core | Redis Compatible
22:08
Milan Jovanović
Рет қаралды 23 М.
Implementing the Result Pattern In ASP.NET API
16:50
Codewrinkles
Рет қаралды 4,4 М.
Modular Monoliths Are The New Microservices
31:08
TaleLearnCode
Рет қаралды 25 М.
5 Design Patterns That Are ACTUALLY Used By Developers
9:27
Alex Hyett
Рет қаралды 297 М.
Don't throw exceptions in C#. Do this instead
18:13
Nick Chapsas
Рет қаралды 261 М.
Dependency Injection, The Best Pattern
13:16
CodeAesthetic
Рет қаралды 872 М.
Não sabe esconder Comida
00:20
DUDU e CAROL
Рет қаралды 64 МЛН