Entity Framework Core Generic Repository: Blazor Blog Example
February 14, 2025
• 1,667 views
In this video, we'll move to a generic repository pattern around Entity Framework Core. We'll even see how this is actively used in a Blazor Blog Engine.
View Transcript
in this video we're going to look at using a generic repository around Entity framework core and we're going to do this within the context of an aspon at core web app hi my name is Nick centino and I'm a principal software engineering manager at Microsoft this video is another entry in the playlist for repositories and caching so if you haven't checked that out I would recommend checking out this link up here that I'll have that will link you to the playlist you can see the other videos these are going to be little building blocks and stepping stones that you can piece these things all together it is going to be set up such that depending on what you're interested in you can check out different videos you don't necessarily have to watch them all from the beginning to the end but maybe you can piece
meal them together and kind of structure your learning how you would like with this video I will be skimming over some Concepts that I covered way more in depth in the previous video which you can check out up here in that video I go into some of the more basic details about how we can set up Entity framework core but in this video we're going to be going from that previous setup to a more generic repository interface let's go ahead and dive into Visual Studio to kick off where we left off all right so inside of Visual Studio here I have the previous Entity framework core repository we had that is meeting this interface I entity repository but what we noticed at the end of the last video was that if we look at the methods that we have on here by collapse all these
things down we can see the implementation very quickly we'll notice that every time that we're calling one of these things we're either dealing with an ID that's part of the entity or we're returning the entity right or creating using the entity or updating using the entity there is nothing really specific about properties of the entity on the API except the ID interestingly if we go expand these and we look at some of the details inside of here we're also not really doing anything fancy with the entities on any of these calls except like looking at the ID right so something that's very basic again if we're updating if I go look at this part down here you can see that we are looking at the ID we don't have complex logic inside of our repository implementation it's truly just doing very basic sort of crud
operations create read update and delete and what's cool about this is that if we were to think about other entities that we might want to model in our database as long as they have an ID and as long as we don't really have to do anything complicated with them we essentially could reuse this exact same pattern except the difference is we might want to have a different type here and this is where generics are going to come into play so I'm going to walk through how we can go convert this why we might want to convert it some drawbacks and things to consider and then I'm actually going to show you the engine that's running my blog that was built by Steven gel and that's actually using a generic repository interface so to start things off if you go back up to this repository interface
I basically had to challenge myself to write it this way because when I was putting all of this together I couldn't help myself but to make it generic but really all that we're going to do to transform this is think about the fact that we don't just want this to be specifically an entity repository we want to make sure that this type here is something that can be the type parameter on a repository so we would have something like this a repository of T so if I get rid of that this is what we want to go make but that means that everywhere we have an entity we'll do something like this we will replace all of them with the type T like that now at this point this is really like a generic repository interface so again I will go into some of the
details for why this is beneficial but this is what we want to go code against that means if we go look down here our EF core repository that we had before from the previous video obviously this doesn't exist anymore we need to have the type of entity just like that and interestingly enough you'll notice that if I scroll through here nothing's really complaining everything actually just works very much the same which is a interesting indicator for us right because I was saying that there is no logic that actually really depends on the entity itself but there is a small detail that is worth calling out and that is that if I go back up here there is one property of entity that we need to worry about and that's the ID because up here at the top this tyght parameter T doesn't actually have any
constraint on it that it needs to have an ID property this is going to be something that we're using I also just realized that I had a capital I up here and that's going to drive me nuts so the point is that we need to make some type of constraint on here because this won't work exactly how it's provided so I already have this coded up and what we're going to do is show that we have another whole implementation of this that essentially looks almost identical to we have here it's just that it's going to use the other repository interface that I've already made we'll talk about the constraint we need to put on it and then it has a different name so let me go ahead and revert some of these changes and what I'm going to do now is move over to the
other folder so I have this other folder over here and we will pop this thing open so you'll notice that I have this eye repository I'm going to go jump over to this and after it's been formatted this is very much like what we just saw it's just that I have it in a different name space but otherwise this is what we just built right so the interface itself that we're looking at here does not have any type constraints that makes things nice and easy if we just want to go work with a repository we can just go have any implementation that meets this very simple interface but now let's go look at the implementation that we have to have and that's where you're going to notice that there is a difference from what I had on the previous version of this and that's going
to be that yes I am implementing this interface yes it is going to have the type parameter of T entity here so you know we Define the class with a type parameter and then sort of pass that in but an Entity framework core in order to make all of this code work the way that the other repository was working we need to have a constraint that we have an ID on entity so the way that I've accomplished that is I've said that every entity we want to work with so this type parameter T must be a base ENT personally I am not a huge fan of Bas classes and Abstract classes if you've watched other videos I've made things like inheritance I try to avoid at all cost but I felt like this would be a good example of showing where we can use it
if we go look at the base entity this is just going to be an abstract record that has an ID on it that's all and that's because everything that our repository will use must have an ID so if I go back here that type constraint right here on line 8 means that anytime someone wants to make an instance of one of these things they must use an entity type that is inheriting from base entity what that's going to do is allow us to have this type of code down here so if I hover over on line 23 on the ID property the reason that this works is because it knows that the T entity that type is going to have an ID you can see in the tool tip it's saying base entity. ID it knows T entity must be a base entity and that
way it can access ID otherwise everything in here is the exact same as the other repository we had the formatting is a little different cuz I didn't put everything on new lines like this so if you have watched the previous video and you're saying something looks a little bit different it's this type of thing but otherwise it's the exact same and that's why I tried to show you that little brief refactoring before jumping over here because once I was able to change the interface you could see that nothing complained about the compilation and technically if I would have tried to build it was going to complain that there were two eye repositories but hope you get the idea that inside the internals the implementation of this class did not have to change okay so now we've seen how we can go change this existing repository
we had to being a generic one again it had the constraint that it doesn't really have to deal with any fancy logic specific to the entities but let's talk about some of the reasons why you might want to do this and some of the reasons where this will not work one of the reasons this will not work is if you have more complicated entities or more complicated logic inside of these methods you have for example if you wanted to have your repository getting entities but the way this had to work is that you always need to filter out things that had like a an enabled or deleted flag or something on them if you needed to do that for specific entities and not others you would either need to change this API to allow you to pass in some type of filtering mechanism or you
would need this method directly to be able to support that so if you have custom logic that has to happen per entity type that might be a reason why having a generic repository might not fit for at least that type of entity depending on how you've set up your code with Entity framework core if you feel that you need to be doing other types of joins or other fancy logic inside of the implementation of this repository this might be another reason why a generic one just won't be a good fit for certain entities that you have and of course there's a hybrid scenario here too you might have some entities that are very simple and I will show you that in just a moment when we look at the blog engine so you might have some that are very simple and you might have other
cases where you need your own specific type of repository for more complicated entities I'm not here to say that it's bad design if you have entities that are more complicated that's up to your situation and for the same reason I've mentioned this in the previous video but if you're watching this and you're feeling in your heart that having a repository over the database context if you're feeling like that's Overkill that's too many levels of abstraction that's totally cool I am not here again to tell you that this is the only way or this is the right way this is how it can look to use a generic repository interface around Entity framework core so I just wanted to get that out of the way in terms of talking about some of the benefits what I want to show you is how we can change up
some of this code I am going to show how we can replace our repository that uses Entity framework core and a bit of a spoiler alert because we're going to drop in a Dapper one and that will be another follow-up video but we'll be able to switch between those two without changing code which I think is really cool and then that will also be a segue to some of the future videos where we're going to talk about caching and that's because we might be able to go make something that is a repository with caching that wraps other repositories so stay tuned for that that's going to be one of the future videos but this is like I said a building block and explaining some of these things if I jump back to the main entry point of this program like I said I do recommend
at least for this video that you watch the first one and that's going to cover why this is set up this way so if you're wondering why we have get methods for all of these crud API calls it's just because I'm calling it from the browser and I wanted to keep it simple I didn't want to use Postman for this or anything else just wanted to hop over to Chrome but what we're going to do is get rid of the entity repository so we are going to put in this instead like I had mentioned me writing I entity repository like this it actually felt like it was a a struggle for me to do because I automatically wanted to go to this the interesting part about having our code set up this way with just having a repository that uses this typ parameter is that
yes of course we can go swap the implementation but we could have done that before right we didn't have to use this new interface we could have used the previous one and swapped the implementation but what's really cool is that we can actually use the same implementation that we just looked at and use it for different entity types it's a different way right you instead of saying we want to swap the implementation we can actually take the implementation and leverage it for different entity types this will be more apparent when we go look at the Blazer blog engine in just a moment what I'd like to do up at the top here is I have this left over from the previous video and this is where we were setting up dependency injection I'm going to use setup EF crud generic we're going to go have
a look at that so if we jump into here you can see that I am setting up Entity framework core it's going to use SQL light and then you can see that I am adding a Singleton and it's going to meet this interface I repository with the type parameter of entity that's in the angle brackets there and then we have this EF core repository that also has that same type parameter with entity in it this is the generic implementation that's going to get wired up to our dependency injection so jumping back here what this application should do for us is we set up our asp.net core app we add these minimal apis and then when we call the minimal apis the dependency injection framework is going to allow us to access that repository which is the generic one okay so what I've done is started
the website now I've gone over to sqlite expert I had some records that were already in the database if I take this record here the one that ends in 930 for the ID it has a value of test that means if I jump back over to here and I paste this into the browser this should call our get method so let me put a breakpoint here and now if I press enter we should hit that that means if we look at the repository that's passed in the type parameter is going to be EF crud generic and that is the one that is from this folder here on the left in my solution explorer that is the generic repository implementation so let me go jump into this and we can have a look you'll notice that in the bottom right that when I try to jump
into that method again a spoiler alert you can see that there are two implementations we have a Dapper one and an Entity framework core but this is the one that I've jumped to in Entity framework core with the generic type parameter so if I run to that we will hit that and we should be able to go get that record and return it back to the browser and of course worked nice and simply so we can see an API call on the web that is going to go to our repository so that sort of the layer that we put around Entity framework core and then asking Entity framework core goes to our sqlite database looks for this ID and then gives us the entire record back and like we saw that's going to mat match this one right here now the other methods that we
have look very much the same so if you've watched the other video and you got to see me step through the code there's not going to be anything very exciting for me to go repeat that so I'll save you the time the point of watching this so far was that we can swap over to a generic interface and now what I'd like to do is cut over to the Blazer blog engine which is what I'm running my website with and like I said Steven gel has put this together that's what he's running his website with as well this other instance of Visual Studio I am using Steven gel's repository here you can see that it's repository with a type parameter he has a generic interface and he also has this wear T entity inherits from entity if we jump over to this same type of
thing right he has an ID on an abstract class I used a record and then he also has this default setting here so let me jump back there's a few other things that he has inside of his is like a health check but the rest of the patterns are very much the same right he has a get by ID anything that we're seeing in here is going to be very generic and there are some interesting differences so one that I wanted to call out that I didn't build into my example but he has it here is we can use this part right here this filter the idea with this is that he has an expression that you can pass in when you call this and because it's a generic repository whoever is calling this can provide an expression for filtering things this repository implementation itself
it doesn't have to know if you have an entity that has 10 other fancy properties on it it only knows about the ID because the implementation only cares about the ID however you as the caller to this repository you might say yeah I'm dealing with blog posts and sure a Blog post has an ID property on it but me as the caller I want to get all of the blog posts that were posted after the 1st of January in 2025 instead of having to go build a custom repository for that just to be able to have logic inside of the method that allows you to go do that filtering because of Entity framework core we can leverage expressions and that means that you can just write code that says where blog post do you know post date or whatever the the property is is greater
than that date and the Beautiful part about this is that Entity framework core will go translate that into SQL for you if you're backed by a SQL database it's a really powerful feature and instead of having to go build custom repositories and having all of like you know 10 different implementations because you have 10 different entities you can essentially abstract a lot of that and make it very simple just by having these Expressions that you pass in and again just to to repeat it one more time the caller of this would know that it is dealing with blog posts the caller would be able to provide this filter the implementation that we're looking at on the screen does not have to care at all about the type of the entity as long as it has an ID and that's because some of the other methods
if we scroll through them they actually do use the ID so just to prove how much this gets used across this particular project if we jump over to the blog DB context file we can see that there are tons of these entity types that are basically going to be able to have repositories wrapped around them so if I wanted to to go look at what skill is you can see that it's going to inherit from entity we could go use this in that generic repository we could go over to user record and again it's an entity so we could go use this in that repository we don't have to go code 10 different repositories or however many there are right here just because we have different entity types all right so to quickly recap in this video what we were able to do was start
with a more specific repository pattern then we could make it generic and that's because the implementation we were dealing with did not have to deal with any specific information about our entities except the ID in order to make that work we introduced a base entity that implemented an ID on it so that way people that are creating their own entities they just have to inherit from that now now they don't need to go make their own implementation of repository they can just leverage ours because we can just use the entity type so T entity as the generic parameter with a type constraint and pass that all the way through our own implementation some places where this doesn't really work very well is if you do need specific Logic for your different entities another instance where this might not work as if you have more complicated
entities and they're not just trivial to pull back through Entity framework core depending on how you've set things up and some instances where you do want this are like we just saw with the blog engine if you have a lot of really simple entities and you just want to be able to leverage the same implementation awesome Works super well and another thing is when we start to look at caching there's some cool things we can do by having a nice generic interface like this thanks so much for watching this one remember to check out the playlist with the other videos around repository patterns and caching and that way like I said at the beginning of this you can kind of pick and choose the direction you want to go whether that's looking at more building blocks or jumping ahead to more things like cashing and
more advanced things that you can leverage thanks and I'll see you next time
Frequently Asked Questions
What is a generic repository in the context of Entity Framework Core?
A generic repository is a design pattern that allows me to create a single repository interface that can work with any entity type, as long as that entity has an ID. This means I can reuse the same repository implementation for different entities without having to write separate code for each one.
Why would I want to use a generic repository instead of a specific one for each entity?
Using a generic repository simplifies my code and reduces duplication. If my entities are simple and don't require complex logic, I can leverage the same implementation for multiple entities, making my code cleaner and easier to maintain.
Are there situations where a generic repository might not be the best choice?
Yes, if I have entities that require complex logic or specific operations that differ from one entity to another, a generic repository might not fit well. In those cases, I may need to create specific repositories to handle the unique requirements of those entities.
These FAQs were generated by AI from the video transcript.