Repository Design Pattern With Entity Framework Core
February 12, 2025
• 3,233 views
This video kicks off the series on the repository design pattern. We'll look at how you can set up EF Core in an ASP NET Core web API and wrap it up in a repository design pattern!
View Transcript
in this video we're going to look at a repository pattern with Entity framework core inside of asp.net hi I'm Nick centino and I'm a principal software engineering manager at Microsoft this video will be part of a larger playlist which I'll link right up here if you want to check that out and we're going to be talking about repository patterns databases and caches all together inside of practical examples now some of these like this video will be more introductory more foundational and the intention is just to get the ball rolling to expose you to some of these Concepts that means that we won't be doing a super deep dive into Entity framework core or coming up with the most optimized way to do these things but what we're going to do is create some of the building blocks so you can progress through leveraging these Concepts
that means if you are an expert with Entity framework core caching and that sort of thing you may want to move into other videos inside of this playlist but otherwise if you're just getting started want to understand what a repository pattern looks like how to leverage Entity framework core and then later be able to leverage caches this might be a great place to start now let's jump over to visual studio and start walking through some of the code what I have in front of us now is a sample web application inside of asp.net and I have four get methods this is not traditionally what you would be doing because if we're going to talk about something like a crud application with create read update and delete you would be using different HTTP methods but because I'm going to show you this example just by going
into the browser I did make them all gets just to keep things simple so I'm just calling it out this is not what I would recommend but this is just to make it easy for us to see in the browser so if I start expanding these you'll see that I have a get method which is going to be taking in a repository which we'll see how to go build this we're going to pass in an ID and then we're going to ask our repository to get that so this is the Reading part of our crud API that will leverage a repository if I expand these other HTTP methods we can see that we have the create part so I'll talk about how we go create an entity go call the create method on our repository we'll have a delete and we'll also have update so
at a high level I just wanted to show you that we have this simple web API again all get methods not what I would recommend but we're able to go exercise our repository that we'll be building so because we have these four different methods at the high level of our web API that means we're going to need a corresponding set of methods on our repository that we can go access you might be asking yourself okay well what exactly is a repository then and this is a design pattern that generally is used to be able to control data access that means when we look at the code that's on our screen right now I have been telling you that we'll be doing things like getting data creating data updating it deleting it so we're manipulating data in some way but I haven't told you exactly how
that data is stored so it's like an abstraction that sits on top of your data storage now for this video what we're going to be using is sqlite just to keep things very simple I don't have to run a database server anywhere it's simply just a file I'm calling that out because as we go through setting up your repository if you decide that you would like to use a different database you can absolutely switch to that because we're using Entity framework core you will be able to swap to different implementations there are other packages that let you leverage those other implementations I'm just going with sqlite for Simplicity one more little bit of house keeping that I want to talk about is that the entity we're going to be working with if I jump over to that code is extremely simple there's not a lot
going on here it's just going to have an ID and a string value so if you're thinking about a real application that you're building you're probably going to want to have entities that have other types of data on here I'm just doing this so that we can see that we're updating a value and then we have a way to refer to our entities more specifically this is inheriting from a base class so if I jump into that we'll see that this is a base entity every entity will need an ID this isn't going to be extremely important for this video but if you're going to watch the other videos that follow up on this you'll understand a little bit more clearly why I've included a Bas class here I'm not a big fan of including Bas classes but this is a way to simplify how
we can build out other parts that will come later okay so we have a crud web API we know that we're going to be using a repository but we haven't really seen how that works yet and the entity type that we're dealing with which is really just the data that we're working with is pretty simple so what do we start to do when we're working with Entity framework core well one of the first building blocks that we need when working with Entity framework is we need a DB context so we're going to go look at how we create our own DB context you'll see that I start off with this class on line six I Just Called It app DB context and then it must inherit from this DB context inside of this Constructor I'm calling database ensure created this is something that you may
want to do in different ways like I said this is just a beginner introduction to this concept I'm not going to dive into all of the nuances I just want to expose these different things to you so you can go explore them this part here on line 14 is going to be a very important part of working with Entity framework core the naming might be a little confusing because I called it entity and you might be saying well what is an entity this might be better explained if we had a more specific repository say like a blog post Repository or if we had a repository of social media posts or some other type of data maybe you wanted to have a repository with models of cars you could have a car model on your repository this is just the set of data that is typed
entity and we've called it entities so when we go to work with our data I want to be accessing the collection of entities this is what we're exposing out to people working with our DB context now Entity framework does allow us to override on model creating because if we're trying to ensure that it's created we need to make sure that we actually create it so we have this model builder apply configuration and if I scroll down a little bit more because we only have one entity type inside of our database and it's just the entity we've already seen we can create a simple configuration just like this one now what we're doing is we're ensuring that it has this key that's called the ID property and then we have this property on the entity called called ID and this value generated on ad if we
look at the tool tip for this it says configures a property to have a value generated only when saving a new entity unless a non-null non-temporary value has been set in which case the set value will be saved instead so the value may be generated by a client side value generator which is what we'll be doing we'll be providing the value or may be generated by the database as part of Saving The Entity so some database engines will allow you to have a schema that creates a value when you're creating a new record so we are going to be controlling that outside of the database but I just wanted to explain that you have this option here now value is another property that we have on our entity and we're saying that it is going to be required but doing all of this means that
we should be set up when we try to leverage the stb context that we're able to have a database schema created for us to use this is one of the building blocks that we must have when using Entity framework core you can see on my screen right now there is no SQL code written anywhere I mentioned that we're going to be using SQL light for this example but as you can see this is going to help us ensure that we have that schema without writing any SQL light which is great so going back to the program.cs what I wanted to call out is now we have this idea of a repository we have an highlevel overview of our crud API we've seen the basics of an entity and now we know one of the building blocks for Entity Framework core so how does that DB
context and the repository pattern come together many people will debate this online and I'm not here to tell you which side to pick some people will say hey if you're dealing with Entity framework core you absolutely don't need a repository pattern it's Overkill it's just too many layers of abstraction other people will say hey you want to hide that detail that you're working with Entity framework core you absolutely want to wrap it in a repository so that that's a detail we don't have to see I am not going to tell you what's right or what's wrong because I think that will depend on the context this video is talking about wrapping the database context in a repository pattern if you're against that idea you don't think it's going to be suited for your needs then you don't need to do that you don't need to
feel like I'm forcing you to do that I'm just showing you how we can with that said we have to find a way to take this repository interface and I've only briefly showed you how we can call it we haven't even looked at the interface we need to see that and we need to understand how that's going to work with our DB context let's go look at the class and the interface for this repository if I jump over to this file here you can see at the top I have an i entity repository and this is going to have all the methods that we want from our crud API that we can call so we have this create method you can see that at a quick glance here these are all async calls I'm using value task this is a detail that will come up
a little bit later you might be saying y value task and not task maybe if you're newer to a syn8 style code in C you might be saying I didn't even know there was a value task it's not something that's super common that I think people are thinking about but we will touch on this later when we talk about caching so don't worry too much about it for now if you're finding it confusing just pretend that this is a task for now and then we can get into those details in future videos when we're calling create on the repository we're going to pass in The Entity that we want to go into the database when we're calling delete all that we need to specify is the ID of the entity that we want to delete and the return value is going to be whether or
not that thing got deleted so for example if we only had one record that had the ID 23 and we said go delete ID 456 this won't throw an exception it will just return false so just an explanation of how that works I did include a get all method here because this is something something that might be pretty common to have on something like a repository we're not going to be leveraging it in our crud API but if we want it to be able to get everything we could do that get async down here is just going to take in an ID that we want to look for and it will return that entity if it's found and you'll notice that this is marked as nullable because if we don't find one instead of throwing an exception we'll just return null and finally the last
method that we have is update so we will pass in an entity and and if it does get updated then we will return true otherwise false this is a bit of an interesting one we'll see when we look at the implementation of this because I think that there's different ways that you could think about this API just a reminder that as I walked through these methods you might have a different idea of what you would want on these different API calls in terms of the the parameters that they're being passed maybe if you wanted a get method you want to pass in an expression to go look things up this is just a highlevel overview and I want to encourage you that you should be going to explore these Concepts further this is just an intro video to walk through some of the basics now
let's go see this class how do we go take this interface which is what our callers will see right our crud API will be calling this thing so that means it sees these methods but if we want to go wire that up to that database context how does that all look so that's going to be in this class right here called EF core repository you'll notice that it's inheriting from I entity repository what we're going to do is pass in an idb context Factory again if you're very new to Entity framework core I haven't touched on this part yet but you'll see that on line 31 the type of the DB context Factory is that app database context that we talked about this is the one we've already seen so the idea is that we want to ask the context Factory to create a context
for us when we're going to work with the database that means that at this point if we're looking from lines 31 to 36 talking about the Constructor being called what we're not doing at this point is opening up a direct connection to the database that's not what's happening we're providing in objects that allow us to go connect to the database when we need to I just wanted to make that very explicit this is not opening a connection to the database when we start calling the methods down lower so say for example down here when we're exercising this code this is where we will be able to go have a connection to the database if you're dealing with more complicated multi-threaded applications especially if you're running something like a web server if you were just using one database context and passing that around everywhere you may
encounter some challenges which is exactly why we want to make sure that we have a factory to be able to create it so we can use it only in the scope that we're working with it again if that sounds confusing and you want more details on that I do suggest you watch additional videos because this is just an intro so we can see some of the patterns okay so if we start stepping through some of the implementation here the common thing you'll see is that all of these will be creating a DB context right so we have the factory we're going to ask to create an instance of that context it is disposable so we want to make sure that we have a using out the front if you're not familiar with what using is this just means that this is something that is marked
as disposable when we leave the scope of this method it will dispose of it you might have seen this pattern before this type of using statement is a little bit newer depending on when you're watching this other times you might see that it's using and then you have to have the entire block of code scoped inside of a using block this is just going to be the same thing except when we exit this method it will essentially call dispose before leaving just a heads up if you're not familiar with that on this next line 44 through 48 we can see that we're using that context and we're asking for that set of entities so this is kind of like the collection that we're trying to access and then we're going to ask for the first or default which means we're going to look for something
that matches this pattern here which if you have a close look is just saying give me the one that has the same ID and if we can't find it what it will do is return the default of entity our case that will be null so this code here is essentially going to ask our SQL database behind the scenes thanks to Entity framework core hey go go find me the entry with this ID if you cannot find one give me null one of the main reasons that people love using Entity framework core is that this block of code right here and what we've seen so far you have not seen anything to do with the database people love this if you don't love writing SQL and you want to keep that completely abstracted you're essentially able to work with the database without writing any SQL code
that can be awesome for me personally actually like having SQL I use different things called Dapper we will see that in future videos but what I wanted to mention just a little bit more specifically here is that when you're exercising this this will go run SQL code against your database it's just that transformation happens behind the scenes for you let's move on to get all async this one's going to be very similar like I said it's not actually leveraged from our crud API I just wanted to show you so similar thing get the DB context and then here we don't have a filter right we're not using first or default because we're not looking for a specific ID we're just saying take that whole set of entities and let's go map it to an array that way we get the whole thing back this may
not be something you want to do on a database with a ton of Records if you're dealing with a table that only has a few things in it and you know that for sure this could be a method that you want I've certainly built applications where I have a table of configuration values or something like that and I know for sure that I can safely pull those all into memory not be concerned and I've written some other applications where that would be absolutely detrimental if we said hey there's a million records in the database let's go pull all those into memory not going to fly so well this is just an example but I wanted to warn you that if you're not thinking about the data that's in the database this might not be something that you want on your repository so consider that next
let's go to create this is going to again start off with that DB context being created and you can see that on the set of entities we're calling add async and passing in the entity when we were looking at setting up the appdb context if you recall when we were ensuring the database was created we said our entity has an ID and a value and we said that ID could either be created from the database or from the client side when I'm designing repositories personally I like ID creation to happen outside of what I would call my data layer so I personally like my application layer that sits above the data layer to be responsible for creating those IDs but there may be other use cases perhaps where someone says hey always let the database create the ID or always let my data layer so
still in code not in the database I want that to create the ID so in here like in this method you would be setting up the ID but the way that we're going to see it is that when we call create a sync we will be creating an entity with a new ID I just wanted to mention that because like I said this is an introduction and if you want to understand those Concepts better now you might have a bit of framing for other things to go search so in the database to create your ID in your data layer like right here or the calling part that's above this so maybe in more application logic there's three different scenarios that I just gave you you could probably think of more perhaps and maybe the reasons that you want to do that will change so something
to consider now let's go look at update an update is probably the most complicated one we have and I did mention that depending on how you want to go Implement update you may have a different perspective on what should happen here so I wanted to walk through this because it deserves a little bit more attention we start off the same way we've already seen this a handful of times what I'm going to do is in my implementation of update I only want to update an entity if it exists so how I wrote this in here says let's go check if it exists so what I'm doing is asking for the first or default so this is very much like the get we had if we scroll back up right you can see that we're doing first or default based on the ID let me scroll
back down same idea here however what's happening is I have this as no tracking this is a huge tool tip to go read through but I'm going to explain why I'm doing this if we check if the thing exists and we say hey wait it doesn't I don't want to perform any further action some people may want to have something that's like an upsert or a update or ad you may want to do something different in my case I'm saying if it doesn't exist we're not doing anything at all and we're going to return false if we go down a little bit lower you can see that what I'm doing is I'm taking the entity that was passed in and I'm setting the state of that entity to be mod ified then I'm calling on the DB context to save those changes back into the
database what's interesting here is that if I do not have asnot tracking and I try to perform this action what could happen is that it will say hey look there's already an entity that has the same ID and you're trying to basically save the changes back but I have these two things being tracked what am I supposed to do so this is a little bit more detail into Entity framework core if you want to understand these things more in depth please continue watching other Entity framework core videos this is just an intro to repositories a different way that we could probably do this is instead of me uh trying to save this one right so if I'm marking this one as being modified what we could be doing is trying to copy over the values from the other entity and then we could go save
that but I'm not doing that here I'm not even using using that entity that comes back I'm simply checking if it exists so there's different ways you could do this we could also like I said maybe we wanted to add the entity if it doesn't exist I'm just trying to show you that if you want different behavior in your repository these are different things to think about again if you want to go Implement different things you have a different approach to this no problem I'm not telling you this is the only right way or anything like that just some options let's go look at delete and delete is kind of similar and that we are checking if something exists first that way we can go remove it from the set and then we can save the changes so very similar we're going to try finding
the thing by its ID right so we look for it if it is null we don't have it then we're just going to return false we didn't delete anything we're not going to throw an exception just say hey nothing to delete if we did find it though we're taking that reference and we are removing it then we can save those changes Mac to the database overall these are a few different methods that we have on a repository and how we can take that repository interface and call the needed methods an Entity framework core if you can see if I just collapse these this idea is that we basically have one more level of abstraction over Entity framework core with our repository and like I said before walking through this part of the code some people will say that's absolutely Overkill I just don't want to
have to deal with that that let me literally just go wherever I need to go do this kind of thing just work with the database context itself so I'm not here to tell you it's right or wrong just showing you this is how you could wrap a repository pattern around any framewor core let's go back to program and see how we can wire these things up and then we'll actually start calling this from the browser to make this work if you're not familiar with dependency injection in asp.net core I have other videos on that there are plenty of other videos on YouTube you can go watch but what we're going to be doing is leveraging dependency injection so we can use these services and that way if we go back to our minimal apis like right here for example when we say give me the
entity repository this will ask our service collection hey do you have an implementation that meets I entity repository and thanks to dependency injection which we'll walk through in just a moment we'll be able to find the instance that we need let's go into set up EF crud this is an extension method that I've created and what we're going to be doing is on our web application Builder we will ask to add the DB context Factory specifically for our app DB context this is the one that we created we've already walked through it when we were looking at our repository this is the type of the DB context we were using that has that set of entities directly on it so we've already seen this this is how we add in dependency injection how having that DB context Factory and for the first time you're seeing
some sqlite specific stuff we're saying hey when we're using this DB context it's going to be sqlite and this data source this is the connection string that's right in here this connection string just says the data source is going to be test. DB you could use an in-memory database if you're using sqlite you can use a file if you're using other databases instead of use sqlite you would have something like use and then you could say uh like MySQL or you could have SQL server or postgress lots of other options we're using sqlite here so that's setting up Entity framework core to connect to our database beyond that the only other thing that we're adding in to the dependency injection framework is a Singleton so there will be one instance of this ever which is going to be our repository something to think about here
just to make sure we're all on the same page is I'm saying one instance of the repository that doesn't mean one instance of the DB context recall up here we're adding a DB context Factory every method that we saw inside of our repository is going to ask that factory to make a new instance of the DB context for us it will say hey Factory give me that instance of the context so it's not one context it's one Factory and one repository just to be clear because this might be confusing for some people people when they see Singleton the reason is this uh repository does not need any state and we don't need to make sure that we're managing that state and having separate instances so just a heads up that's why this is a Singleton with all of that put together that means once we
have this Builder Line run and we set these up we've now configured Entity framework core and we've hooked up an instance or the type that we need to have that meets our I entity repository we're off to a great start here so at this point we should be able to go run our web application call the crud methods that we have and see that it's actually taking an effect and I think what would be helpful is if we start with the create because we haven't talked about creating that ID I'm just using a random number here but let's go check this out we're going to call create and get this thing running okay and just to show you that it's up and running it says it's listening on Local Host 7230 we don't really need to watch necessarily in here so I'm going to minimize
this for now we are going to go over to the browser though and try to position these in a way that you can see them and that I can see them too because the camera is in front of everything but we're going to do a create call now recall that I did say that these methods here uh are all HTTP get methods probably not what you would want to do when you're building out an API but this is just so that I can call it in the browser and you can see it so we call create we're going to hit our breakpoint what we're going to do is create a new entity so so if I hover over this yes uh I'll have the editor zoom in so you can see what's going on but we have this entity it has a randomly generated ID
this may not be what you want to do like I was saying earlier if you want your database to go create IDs for you incre like that increment automatically you can absolutely do that you can use goids for your IDs there's different uh strategies around that people will tell you different things there and something important to consider when you're building out a real database and in my case here I'm just generating random IDs I would say this is not super great practice because you can absolutely have collisions like this but just to make this demonstration easy I just wanted to have this up and running and show you that we can create IDs at the application layer so something that's not right at the repository something that's outside of that and then the value this part was just for me to go generate any random
value not super important here I just didn't want it to be an empty string now inside of our minimal API I'm going to go into the repository part now so we've created an entity in memory if I step into this well it didn't step into it it just executed very quickly so I'm going to repeat it again but let me go pull it up so we can see it did actually go create something so let me call it one more time and I'm going to put a different break point a little bit lower for us so let me go into here and I will instead run to this part so just because I don't trust my debugger right now if I press F10 see we got the DB context made right we have an instance of that DB context great I'm going to call this
line now where it will add but we haven't save the changes right so this added it to the collection but this is going to actually cause Entity framework core to go write that data back to the database so if I go do this now we have added that record you can see if you pay attention down here that the SQL part was actually being exercised just to prove it if I pull this up too I was saying we didn't need to go watch up top here but you can see that it has a DB type integer for the first parameter and then it has a question mark for the second parameter because I have a a string there and then the actual SQL that was run against the database is insert into entities and then it has ID and value because those are the two
properties on our entity type and then the values that are these two parameters this is the part that you don't have to think about when you're using Entity framework core we didn't have to write any SQL so this is one of the main reasons that people love using Entity framework cores we don't have to think about this for really simple things when it gets more complicated and you're debugging stuff that is a lot more complicated than just a simple entity table like this yes it's probably going to be very helpful to understand the details of SQL but for this case probably not that important so let's go back we can step through this and when we go to return this we can see that we're just going to pass back the entity to the caller that is how we create one great we have this
I'm going to zoom out a little bit we have this ID now though okay so what is another method that we could go do well let's see if we can go get this entity back what I'm going to do is we're going to look at FF right at the end of this guid that's one of the drawbacks to using guids and making videos like this is like hey go memorize this everyone and I don't want to copy it somewhere else so we're just going to remember F A CF at the end now our get API if we look right up here on line 11 is just going to be right the root and then I'm going to pass in this ID now when I press enter I'm not putting a break point on here on the get method but we should see if we think
about what's going to happen line 16 will go to the repository which calls Entity framework core looks for a record with this ID and then it will return it to us we should see this exact same text come back so let's go try it and there we go the exact same text came back because that is the entity that was matched If instead I change this ID to be something completely different so I put 222 here instead and I run this you can see that we just get nothing back so that's because when it returned okay The Entity that came back was null so not a great API design but that's why we don't see anything here so that's the reason for it if I put 175 back you can see that we are getting that entity so so far so good we've done create
and we've done a get let's go update this thing though so let's scroll that into view update down here and maybe we should step through this one because this might be more interesting but if we have this part and we want to look at update that means we need to have a slash update here and then the ID but then we need to give it a different value so let's call it Dev leader for the uh value which is here okay so these are the two parameters right ID is on line 41 value is on line 42 if I press enter here we should be able to go in because my debugger is being a little bit funny I'm going to put a break point here and here and here so F5 into here let's see does this thing exist if I press F5 again
and we hover over exist it says yes it does in fact exist I'm going to jump down to here we can see that we're going to take this entity which is the one that we created at the minimal API level it says that the ID is the one we passed in Dev leader is the value right from the URL bar we're going to set that state to modified and save it did it all at once because my debugger is being very funny and then it returned true because our minimal API is saying if it does update it will return true let's go back and get it calling this and you can see that when I call get now this is the value that was in the database now because that's what we just updated it to if we want to go back to this and
let's go change this to be 222 instead right so we're saying we want to go update this record ID we know that doesn't exist I just made this up and we want to set that to be Dev leader when we go into here again I'm going to jump over press F5 we should see that when I press F5 one more time that exists is false and if we have a look exists is false because the ID was not found now when I leave here it will return false all all the way back to the browser so so far so good one more minimal API to check out and that's going to be delete this one is pretty simple let's start by deleting the one that does not exist okay so if I call this uh if we let me go back to here so you
can see we are going to get a Boolean value back so if I try to delete one that doesn't exist what should we see come back in the browser it's either true or false so let's go C we get a false that comes back that ID simply doesn't exist now if I put 175 out here it did apparently delete it but how do we go confirm that it's actually gone well we can go call the get API once more and that get API is right here so now we should see a white screen come back because this thing should be out of the database and there we go we've successfully created fetched updated deleted and then refetch one entity using a repository pattern over Entity framework core so this was just a highlevel overview of how you can wrap a repository pattern over Entity framework
core but in the next video what I wanted to show you is that we can do something a little bit different here this is because if we look at our entity repository that we created and the methods that we have there's something that we can do a little bit differently here everything that we set up here is actually something that could probably be very generic there's nothing really unique about these entities what I mean by that is the only real thing that we need to deal with on the entity is this ID everything else in terms of these apis that we have if we look up here right it's just going to be an ID or entity coming back and even in the implementation there there wasn't anything really fancy going on it wasn't like there was a special property we had to go set
up or join across other things this was just is there an ID that matches if there is give it back if we were updating things it was just hey you already have this entity go market as modified and then save the changes so in the next video what we're going to look at is transforming this into being a generic repository that we can wrap around Entity framework ore thanks so much for watching this and if this was too simple or you want to jump around remember to check out this playlist above and that way you can go pick something that's more appropriate thanks and I'll see you in the next video
Frequently Asked Questions
What is the repository pattern and why should I use it with Entity Framework Core?
The repository pattern is a design pattern that abstracts data access, allowing you to manage data operations without exposing the underlying database details. I recommend using it with Entity Framework Core to encapsulate data access logic, making your code cleaner and easier to maintain.
Why are all the HTTP methods in the example using GET instead of the standard CRUD methods?
I used all GET methods in this example for simplicity and to demonstrate the repository pattern without complicating things with different HTTP methods. In a real-world application, you would typically use POST for create, PUT for update, and DELETE for removing records.
Can I use a different database with the repository pattern and Entity Framework Core?
Absolutely! While I used SQLite for simplicity in this video, Entity Framework Core supports multiple database providers. You can easily switch to other databases like SQL Server, MySQL, or PostgreSQL by changing the configuration in your DbContext.
These FAQs were generated by AI from the video transcript.