ASP NET Core Caching Explained: Hybrid Cache + Redis + Dapper!
May 12, 2025
• 1,055 views
entity frameworknick chapsasefcoremicrosoft mvpsqlef coredotnetchapsasrepository patternrepositorydesign patternsrepository pattern asp.net coresqliteef core tutorialIMemoryCacheCaching C#C# memory cachedesign patterncaching tutorialhybrid cachehybridcacheredisredis tutorialredis tutorial playlistwhat is redisdapperdapper C#dapper tutorialdapper ormdapper sqldapper mappingdapper vs entity framework coredapper rest api
In this video series, we've seen EF Core, Dapper, Redis, and Hybrid Cache... So let's wire up our ASP Net Core application to use the Hybrid Cache with Dapper and Redis!
This video builds on the previous content in this series and we'll see how we can swap out components of the system with ease!
View Transcript
Hi, my name is Nick Coantino and I'm a principal software engineering manager at Microsoft. In this video, we're going to be looking at using Dapper with Hybrid Cache and Reddus al together. This video is part of a series, so I have a playlist linked right up here. You can go ahead and check that out if you haven't done so already. But we keep building on some of these different data access patterns that we have available to us. So in previous videos we've looked at using Dapper. We've looked at using entity framework core. We've looked at using repository patterns. We've looked at the decorator pattern as well. And then we started to introduce caching with a memory cache hybrid cache. We started incorporating Reddus. So lots of awesome stuff going on. But in this video, we're going to be moving from Entity Framework Core back over
to Dapper. So, we're going to be transforming some of that code, looking at how our decorator changes with respect to dependency injection, and then we'll connect over to Reddus and show the hybrid cache in action. If that sounds interesting, just a reminder, subscribe to the channel and check out that pin comment for my courses on domain. Let's jump over to Visual Studio and check things out. Okay, in the previous video, what we had going on here was our really simple application. and it has a bunch of HTTP get methods on it that are are basically like create, read, update, delete. Yes, these are not the right HTTP methods to use. But when I go to demo this, I'm just going to be in Chrome pressing enter in the address bar. So, it just makes it simple for me to go demonstrate this. But what we
saw in the previous video is that we have these lines right up here to be able to set up the hybrid cache. We have a couple of different uh expiration periods for local and for the distributed cache. And then this part down here is where we have Reddus being added in. So again, check out the previous videos in the playlist. They all kind of add together. So that way you can keep building on what's going on here. But what we had is this line up here on line six where we had a dependency injection extension method that we can work with. And I just called it setup entity framework CRUD with hybrid cache decorator. Very verbose. But what we're going to do is change this one because we don't want to set up entity framework core for this video. We're going to use Dapper. But
I want to show you how we transform that decorator just a little bit. And then we can see the really cool part in my opinion is that the rest of our application isn't really going to change. Basically, all the things that I have highlighted right here, that's all going to stay the same. We already have a repository pattern for Dapper. We're going to wrap it with caching and then it's just going to work for us. So part of demonstrating that is just really like the power that we have when we go to use some of these design patterns, right? Okay, with that said, let's jump over to the entity framework core code and we can see that we started building up uh these different uh dependency injection helper methods that we have. So here this is the one we're interested in and what we did
was we extracted some common code just for setting up entity framework core. So that was down here. It's really just like connect to the SQLite database. If you want to use another database for your application, by all means, please do. I just wanted to run something locally, really simple on my machine. So, we have this part, right? The first part is just going to get the basics set up for Entity Framework Core. Then, we're adding in our repository. So, the entity framework core repository. And the types of entities we're dealing with are just called entity. My naming is not very creative, but if you had a repository of books, your entity type would be book in this case, but this is where the decorator magic comes into play. So, we basically want something that looks just like this for Dapper. So, I'm just going to
copy that. I'm going to go over to our Dapper uh folder. So, Dapper CRUD, then builder extensions, and I'm going to drop it right in here. It needs its own name. We have to change up some things here. So, not a big deal, but we'll see how we can start to transform this. Okay. So, set up Dapper CRUD. And CRUD, if you're not familiar with the acronym create, read, update, delete. I know it sounds kind of funny, but we're going to change up some of this stuff going on. And what I want to do is show you basically a sort of a a pattern that we see with the Entity Framework Core 1, but it's actually going to fall apart a little bit here. So, let me explain what I mean. Before we move on, this is just a quick reminder that I do have
a course on C refactoring available on domain. Refactoring is one of the most critical skills that you can learn as a software engineer. And this helps you continue to build upon applications that already exist, making sure that they can scale and have extensibility. I walk you through a bunch of various techniques and give you some examples that we walk through together to see how we can apply these techniques to refactor the code. Check out the pin comment and the links in the description to get this course. Now, back to the video. The first part that we had done with Entity Framework Core is we kind of extracted this core bit of setting up Entity Framework Core. And that's really what's going on inside here. So, we want a helper method to go along with that. But we're not going to do that just yet. I'm
going to show you this sort of mistake that you can make quite easily and then illustrate what happens and then that way we can work around it. Sometimes I think it's really important to see the the don't do this kind of approach and that way I can save you a little bit of learning on your own. So if we don't have that and we're not setting up the entity framework core repository, we're setting up a Dapper repository. So I'll just go replace those right and Dapper repository does not take an entity. It's actually uh built in to the type. So if I jump to it, you can see that Dapper repository is always of type entity. Okay, just how I built it for this tutorial series. But you can see like that's compatible code. Like that works, right? So if we were to go run
this, what's going to happen, right? So let's go ahead and actually do that. I'll copy and paste that. What we want to do is call this from our uh program.cs file. Right? So up here instead of entity framework core, we're going to be setting up Dapper. Right? That's what we want to have happen. And I'm going to go back to the builder extensions because one thing that we could be doing instead, and actually this is uh something that I already messed up, is that what I wanted to show you was that because we want the Dapper repository set up like we already have set up Dapper CRUD. So, wouldn't it just make sense to do this, right? If we call this, we get our repository set up. And that's great. But there is a catch. Okay. So, I'm going to show us this. It's not
going to work. But if you see what the problem is already cuz you're familiar with dependency injection, great. If not, it's a good little exercise. So, let's go ahead and run this. And it should be running over here. So, that's all great. But if I go into the browser, uh-oh, problem, right? So no service for type Dapper repository has been registered. And then you might be saying, well, what the heck? Like we're literally doing that right here, right? Line 23, that's going to return a Dapper repository. And we're calling setup Dapper CRUD. But what we're doing is that we're changing the registered type that when people want to go look it up, it's only I repository of entity. So it's not registered as Dapper repository when you want to look it up. But if you ask for I repository of entity, you will get the
Dapper repository. Okay. So we have a couple of options here. If I wanted to keep this as reusable code because I want to be able to switch it back, mix and match things, then I don't want to change this registration at all. Right? I want to preserve that. Which then means okay, I can't resolve the Dapper repository directly. What if I just say, well, if you're looking for an I repository, then we can just drop that in here, right? When we're creating the decorator that goes around some repository, we want it to be the Dapper one. When it goes around the repository, we need to give it the registered repository. So, when we construct the caching one, then we're going to say, "Go get me the registered I repository." And we can see that's the type right up here. Seems like it should be a
quick easy fix because we're literally saying in this line, that's how we have it registered. But it's also not going to work. So, let's go ahead and run it. Sorry if you feel like this is a waste of time for you. I think it's really helpful because this kind of stuff with dependency injection, it takes a little bit of getting used to and it's easy to make mistakes. So, jumping back into the browser. Okay, cool. Let's rock and roll and press enter. And it's not crashing. That's good news, right? Well, I don't know if this is a worse problem now because technically what's happening is a bit of an infinite loop or some type of infinite recursion going on. So, if I pause it, what's actually happening here? So, it's currently paused. I'm going to go ahead and doubleclick on this part. And in the
parallel stacks, what we would see is that we basically have this call stack where it's constantly trying to go do the dependency resolution. And you might say, well, why is that happening? And it's because I was doing something that's a little bit misleading, and I'm sorry for doing that. I did tell you it wasn't going to work, though, right? When I was highlighting and walking through this code, I said, "Hey, look, we want to go down here. We know that we registered it as an I repository of type entity, right? That's what that's why we wanted to change it. And we know that because we were looking at line 15. Excellent. But line 31 is also doing something that's basically the same. Line 31 is saying I repository of entity as well. Notice how the highlighting in Visual Studio on line 31 is matching up
on line 15. We have two things that are saying if you want to resolve I repository of entity I got you covered don't worry that's not going to work in this case what we're going to do is instead of chaining these together like this we're going to do another little bit of refactoring in my opinion equally as good if not better because it's actually going to work. So what we want to do is at least in my opinion the goal was to really minimize the amount of duplicated code. So, let's go remove the duplication. Right, this is the part that we don't want to duplicate. I'm just going to pull it into a method down here, private static, and the return type is a Dapper repository. So, create Dapper repository. I'm going to paste that code into here, right? It's literally just what the body
of that method up here is. Excellent. That means that I can just call this up here. Right? This code is functionally the same. It's just a little bit of an refactor to pull out the method. Very simple. What I'm going to do now is get rid of that because what I can do instead is not go have this registration. We're not going to call that. I'm going to do this. I'm just going to call the method to create the Dapper repository on the fly. The reason that we can get away with this is because no one in the code base is actively going to be trying to resolve specifically the Dapper repository. The reason that's the case is that the rest of our code is designed to be agnostic to the type of repository. It kind of makes sense, right? We want everywhere else to
be dealing with I repository of whatever the entity type is. Nice and simple. We care about the API. We care about the interface. We should not care what type of repository it is. In fact, it's not even going to be a Dapper repository we're directly accessing. It's going to be the hybrid caching one. That's the whole point of this video, right? So, we have a hybrid caching repository. That's the decorator that goes around our Dapper one. And it's, in my opinion, a little bit more obvious right here. We're literally saying when someone calls this method, we're specifically hooking in the Dapper one right here. And then we did a little bit of refactoring to have this common code create Dapper repository we can use in both spots. So if we ever wanted to switch back away from the hybrid approach with caching, we can just
go use setup Dapper CRUD instead. With that out of the way, go back to program.cs. We're still calling this method. We should be good to go. If I go ahead and press start, we'll pull up the window. Here we are running. Let's jump back into Chrome. If I go ahead and press enter, what happens? Hm. Seems like something's not working, but also it refreshed, right? So, what's not working is that Reddus isn't running. So, our distributed cache is actually trying to go talk to Reddus. Easy solution for this one. So, I'm going to go back over to Docker Desktop. You can see that I have uh if I go to images, I have the currently the latest Reddis image. If I go to containers, I have this one, but no containers are running, right? So, let me go ahead and start this. Important note that
I need to have the right port running. So, you can see that I'm mapping 6379 to 6379. Inside the container, Reddus is going to be running on port 6379. So, I'm mapping the containers port 6379 to that. That means my application will connect to that port and then the container will be able to have that hooked up directly to Reddus. It's a little bit weird. A picture would probably help. I'm talking with my hands, but I hope you get it. So, if I go ahead and run this, we'll get that going. Cool. It should be running. It's already using some CPU. Now, let's go ahead and I think we should just be able to go run this. But what I'd like to do is clear this console here. This one a little bit messy, but let's keep it there. Now I'm going to go back
to the browser and press enter and see how fast that was. Right, it is working, but it's no longer having errors with the Reddis cache. That's because it is going to reddice to be able to get this value now. So that al together is a way that we can see Reddus running in Docker. That's what I had to do at the end there. We got to see that we're actually pulling the value from Reddus because you saw it throwing exceptions before just to prove it. I'll stop it and start it again because maybe you're saying maybe it failed once and it's not going to keep retrying perhaps. Right. So this uh silly console window isn't there we go. It wasn't clearing. So it's a new run of it. Let me press enter on it. Right. The first time it's connecting to Reddus. It's a little
bit slower but now it's all very quick to access the cache. Reddus set up in Docker desktop. That's up and running. We can connect to it. The connection string I have in app settings JSON. If you've watched the previous videos where we're connecting to Reddus, I just left this code the same. You didn't see me touch it here. Then what we got to see at the beginning of this was how we can set up our dependency injection. So we are using what's called a decorator pattern here with a repository pattern. We didn't go through the repository in this video because that's what we covered in the previous videos, but just a quick scroll through. This is the Dapper repository. And then if we're looking at the hybrid caching repository that decorates it, it's like wrapping it, right? We can see that it's basically going to
have the very much the same shape. It also implements I repository, but you can see that it takes in another one along with the cache. When you put these things together, we do have a decorator around a Dapper cache and that decorator is using the hybrid cache. That hybrid cache is configured with a inmemory cache as well as a Reddis cache that's running locally. That's a whole bunch of stuff, but it's a really cool way and to get all this stuff up and running with a cache. And I'm hoping that if you're going through this video series, you're seeing how these pieces work together, how we can mix and match them, we can swap them. If you're someone that doesn't like using Dapper and you want to use Entity Framework Core, you can go use some of the previous video tutorials set up for that.
If you don't like Entity Framework Core and you like Dapper better, then this one's for you and some of the earlier videos show us building up these repositories. So, thank you so much for watching. I hope you find this helpful and I'll see you next time. Take care.
Frequently Asked Questions
What is the main focus of this video?
In this video, I'm focusing on using Dapper with a hybrid cache and Redis together. We will explore how to set up Dapper, implement caching, and see how these components work in conjunction.
What are some of the design patterns discussed in the video?
I discuss several design patterns including the repository pattern, decorator pattern, and how they apply to data access with Dapper and caching.
How do I set up Redis for the caching in my application?
These FAQs were generated by AI from the video transcript.To set up Redis, you need to run a Redis container using Docker. I demonstrate this in the video, ensuring that the correct port is mapped so that your application can connect to Redis successfully.
