Step by Step - Repository Pattern and Unit of Work with Asp.Net Core 5

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello friends thank you for watching this video i am muhammad and today we will be exploring unit of work and repository pattern with af core and dotnet 5. so what are we going to be covering today first we're going to be discussing what is a representative pattern then we're going to discuss the benefit and why do you want to use a repository pattern and then we're going to be discussing unit of work and what is it and the benefit of unit of works then we're going to be discussing all of the ingredients that we're going to be needing in order for us to implement it and lastly we're going to go into the code as always you will find a source code in the description down below please like share and subscribe if you like this video it will really help the channel so what is a repository pattern the repository pattern is talked about a lot especially in the api and microservices heavy world and the dotnet core shines in the repository pattern is a strategy for abstracting data access layer so what is a data layer it's made up of code and application where it's responsible for storing and retrieving data adding removing updating and selecting items from this collection is done through a series of straightforward methods without the need of dealing with the database concerns like on connections command cursors and readers using this pattern we will be able to achieve all of this coupling and keep the domain object persistent and ignorant so as we can see here from the two graphs in the traditional pattern we can see that all of our different application components like controller services syncs and initializers all of them have direct access to our database so there is no like a middle layer which can actually communicate or actually control this communication between our application and the database it's a direct connection while in the repository pattern all of our controllers initializer services and sync directly communicate with the repository and then it's a repository job to be able to communicate with the database and actually execute those commands and vice versa so for example if we're trying to get some information from the database it will first go through the repository and then it will be actually sent back to the controllers for example if it's requesting it and if the controller wants something it will need it will need to communicate with the rip whether you will need to be able to communicate with the database and then so on so forth so the repository is will be able to handle all of the incoming and outgoing requests for the database and handle all of these connections instead of having all of this logic embedded within the controllers initializes service and sync so why do we want to use repository pattern so there is many reason why do you want to use repository pattern but the main ones is first of all is reduced code duplication so basically repository pattern will allow us to utilize dry design principle where we write the code once and we can analyze it everywhere we want in our code so let's go back to our graph so as we can see here if for example a controller one access for example the users table and the service one access the users table so instead of having two logics uh within the one fourth in the controller and one within the service to handle all of the users coming users table communication we only have one code which is rely on the repository where it's actually responsible for handling all of the users tables actions so the second one is loose coupling so basically it's a loose compiling to the underlying persistent technology so in case we need to switch for example my our database from amazon sequel to postgres or mysql only the data layer implementation will need to change not any not everywhere as we are actually consuming it so this will facilitate the change and update and reduce the chance of errors so for example let's say we want to update our database to let's say postgres all we need to do is actually update the repository instead of actually updating the entire application and that way we'll be able to actually have one place where we can actually do all of the changes without affecting the rest of our application so our the application is basically clueless of what type of technology that we are using or what type of database we are using as long as it's getting its information and that way we can actually do some delegation of the work through to only the repository and actually abstract the application from worrying about how it's going to be connected to different types of technologies database technologies so that's why it's really it's a really good added feature to have loose coupling when it comes to the positive pattern now the third point is the stability based on the loose coupling it means that we can actually create some mock database and utilize some mock technology through our repository pattern to test out every single item within our repository or our application because from that we can create a mock database and from that one format we can create our unit test and the last point we want to discuss is actually separation of concerns so what is separation of concerns separation of concerns is separating the application functionalities based on a function so as mentioned earlier so the reason behind a repository pattern is to have everything related to data access in a single place so we don't have all of the logic embedded within our application where we have bits and pieces of different functionalities related to the database scattered around our application so all of the db logic is saved within our repository pattern and for any reason we need to update it all we need to do is update one single place instead of actually going through the application and try to find all of the different layers and then updating them from there which highly increase the chances of errors specifically if the code is really scattered around our application so separation of concerns actually meaning create different components and every component will actually have one single goal or one single functionality that we can actually utilize and with this we're creating a repository libraries and those applica repository libraries will only be responsible for data access layer so the next point we're going to be discussing is unit of work so what is unit of work so if repository patting is our abstraction over the idea of persistent storage the unit of work pattern is our abstraction over the idea of atomic operation it will allow us to finally have fully decoupled from our service layer and from our data layer the unit of work pattern now manages the database states once all of once all of the updates of the entities in the scopes are completed the track changes are played into the database into a transaction so the database reflect the desired changes thus unit of work pattern tracks a business transaction translated into a database transaction where the steps are collectively run into a single unit to ensure that the integrity of the data is not compromised the transactions are committed and roll back in discreetly thus preventing intermediate state so as we can see here from the repository pattern we have something called the unit of work so within the representative pattern we have for example here three representatives we have the item ones the user repository and the card repository and all of these repository they don't they don't directly speak with our users table they're with the tables itself so far the items will not directly speak with the item table the users will not speak directly with the user's table and the car will not speak with the car repository will not speak with a card table what they do is actually they go through the unit of work which is actually a classes and interfaces which manage the connection to the database and from that point all of the work is sent to the unit of work and the unit of work handle all of these transactions before sending them to the actual database we will see how we can implement this and what the actual benefit which comes into the implementation of this unit of work so now what are the benefit of having unit of work is abstracting the data access layer and the business access layer from the application so if you want to implement for example any kind of business logic within our database data access layer we can actually utilize the unit of work in order for it to have this operation so we can have the data access layer apps on the side the business layer on the side and then we can actually utilize them both second of all uh second benefit is actually utilizing the in memory database so for example when we're trying to do uh adding a lot of users to the database for example so instead of having let's say we have a thousand user instead of actually uh opening 1000 connection to the database every time we want to save a user and actually having 1000 calls and verification that our user has been saved correctly what we can do is within the unit of work is we save those 1000 user into the memory and once all of the data is ready and prepared and processed in order for it to be communicated with the database all we need to do is have one single connection open to the database where we send the commands directly to the database where we are able to save those 1000 user and then we can get back the confirmation and uh to be for our application to resume processing so basically instead of having multiple connections simultaneously doing the same thing over and over again the in-memory database will actually handle all of the incoming transaction prepare them store them until it's ready for us to save it in a single request to the database this is a very simple example of in-memory database but it shows you the power of in-memory database where we don't actually have to have multiple connections for example back to those 1000 users instead of having 1000 connection which is going to consume a lot of memory resources a lot of network resources and might cause our application to slow down because of i o issues those in memory will save us from 1000 to one call and this will add a boost to our performance as well to our database health the third point is dependency injection so basically the dependency injection here will allow us to utilize the loose coupling so we are able to actually inject the unit of work into our constructors or onto our classes or anywhere we will use them in our application with dependency injection of instead of having us to rewrite all of the code in order for us to communicate with the database and lastly is the unit test with dependency instruction we are actually able to write a much more advanced unit test and enable test driven development in order for us to make sure that we are covering all of the scenarios that we need to cover when it comes to our application and our database structure so based on those what are the ingredients that we're going to be needing in order for us to develop our application today first we're going to need visual studio code and then we're going to be utilizing the net5 sdk you can find the links on the screen and in the description down below the installation process is pretty straightforward all we need to do is just download them and install them great now let's get started so after downloading and installing vs code and the sdk now we need to make sure that our dotted sdk has been installed successfully in order for us to do that we're going to be utilizing the net version inside our terminal so dotnet does version and as we can see here i have version 5.0.301 which is the latest version by the time i'm recording this video if you have any other number that should be fine if you have any error you need to re-download and install the sdk now that we have done that it's time for us to install the entity framework tool because we're gonna basically utilizing under the framework within our application so we're gonna create a new project using that sorry we're gonna be uh installing the tool using the net tool keyword so that not tool installed global because we want available everywhere on our os and dot not which refer to entity framework and click on enter and since i have already installed it before it's telling me that it has already installed but if you haven't installed it before it will take a few seconds to a minute to get downloaded and installed so after that we're going to be getting our web api so we're going to be utilizing the new keyword so not new web api on and we're going to call it pocketbook great this should take few seconds to be installed great now that has been installed let's go to the directory and let's open it in visual studio code and this should take a few seconds great now that i have our application open the first thing we're going to be doing is we're going to be opening our terminal so we'll have to go to view terminal and inside the terminal we're going to type not build to make sure that application builds successfully and it does and then we're going to type not run and you see the application running perfect and in order for us to make sure it's working let's first check the controllers so it's weather forecast and it's a simple gut so let's take this and let's open our browser and inside our browser we're gonna go to localhost 5000 and we're gonna be weather forecast and as we can see we have the json being returned which means the application is running as it should be great let's go back to visual studio code and let's stop our application so once we have done that the next step for us is we're going to be adding some packages because we're going to be utilizing sql lite and entity framework inside this application so we need to add packages for our application for sql lite as well as for entity framework so the first thing we're going to be doing is we're going to add four packages and the first packages is the entity framework core tool so we start by.net add package and it's going to be microsoft dot entity framework core so this should take a few seconds and let's see if it has installed no it hasn't maybe i typed it wrong let's see again so the next package we're gonna be installing is it's going to be the sqlites.net add package microsoft dot entity framework core dot sequel light this should also take few seconds great the one after that is the entity framework core tools so dot not add package microsoft dot entity framework core dot tools perfect and the one after that it's gonna be the entity framework tool diagnostics so that not add packages sorry add package dot microsoft dot asp not core dot diagnostics dot entity framework core perfect so now that we have installed these four packages we can verify that they have been installed by going to pocketbook.csproj and we can actually see that our uh four packages has been installed successfully which is the asp.net core diagnostics the anti-framework core identity. entity framework core entity framework called sql lights and any framework cover the tools perfect so once we have done that the next step for us is to open our application settings.json and we need to add our connection strings because this is the connection string that our application is going to be utilizing to save our information to our database and since right now this is a demo application we're going to be utilizing sql lite so let's create a new connection string section and we're going to define the default connection and this is uh since this is sql lite we're going to be using data source and it's going to be we're going to call it app.db and let's give it the cash equal shirt great so once we have created our connection string uh the next step for us is to actually start by cleaning our application so the first thing we're going to be doing is we're going to be deleting some stuff from the boilerplate code that the application has given us so we're going to delete the weather forecast class we don't really need it anymore so delete and we're going to be deleting this controller as well delete so once we have done that now let's build our application dot not build and we need to make sure that it's building successfully create build succeeded so the next step for us it will be uh creating our data directory and our application db context so our application db contacts is going to be responsible for all of the communication with the database and the first thing we're going to be doing is we need to create a new folder inside the root application of our at the root directory of our application called data and inside that folder we're going to create the applicationdb contacts class so here we need to create a new folder and we're going to call it data and inside this data folder we're going to create a class and this class is going to be called application db context perfect now once this class has been created we're gonna start creating our application db context so the first thing we need to do is we need to inherit from the dbcontext class and this dbcontext class is provided for us from entity framework core great so once we have done that now we need to initialize it through the constructor and basically we're just gonna pass the db contacts options so how do we do that inside the constructor parameters we're gonna put db context options and we're gonna take the application db context and we're just gonna make called options and then basically since we're inheriting from the db contacts we need to pass it back so we're going to go to base and we're going to pass it back to the parent class and we're going to pass the options great so this is all we're going to do right now within the application db contacts we're going to be adding more stuff to it as we go so after we have created the application db contacts and we are making sure that it's uh it has all of the information that we currently need the next step is we need to update our startup class and enjoy and add the application to big contacts to our startup class so we can actually utilize it across our application so let's open our startup class and inside our configure services method we're going to add the following which allow us to utilize the application db conducts that we have so first thing is we're going to be calling the services because it's part of the service collection and then we're going to add db contacts and then we're going to pass the application db contacts that we have created so application db context and let's fix the references great so once we have add this now we need to add some options because as you remember in the in the constructors we have passed some options so we need to specify these options and basically the options are going to be first what type of database we're going to utilize so we're going to be utilizing sql lite so we're going to say options dot use sqlite and we need to fix the references for this and once we have done this the next step is we need to specify the connection string of where this is going to be able to find the sql database and for all in order for us to specify it we need to open brackets and inside that we're going to put configuration dot get connection string and we're just gonna pass it the default connection that we defined earlier so it's gonna be default connection and after that that's it so just for reference the default connection that we have here is the same default connection that we have added here inside the application settings and here let's make sure it's the same perfect and this application db contacts is the same class that we have created inside the data folder here great so once we have done that the next step uh we're going to be doing is we're going to be creating our models folder and inside our modules folder we're going to be creating our first entity which is going to be the user's entity so inside the root directory we create a new folder called models and inside this models folder we're going to create a new class and this class is gonna called user and basically right now we're gonna build a simple api which is gonna give us back some user information and we're gonna allow us to basically do all of the cloud operations to that user entity utilizing the api and utilizing the repository pattern and unit of work so once we have created the new class now let's fill this class so the first thing we're going to be doing is we're going to be specifying this user's id so prop good it's going to be id and since this is a good we need to add the using system so let's add it using system great and then we're going to basically just have the first name last name and email so prop string first name drop string last name and lastly it's gonna be the email prop string email great so once we have done that now we need to add this user to our application db context because right now we have created the model but we need to be we need to reflect this model into our database and currently there is no way for us to do that so let's copy this and inside the application db contacts we need to add this entity so how do we add that it's very simple we're going to be utilizing dbsats so it's going to be public virtual tv sat we're going to pass the user class and we're going to call the table users and basically here we're just going to specify the cutters and the setters and basically here we're utilizing the entity framework code first approach to create our database and utilizing it if you want more information about the entity framework and the code first approach i have another video which i delve deep into that which i'm gonna be linking here on the upper right hand side corner great so once we have added this let's add a comment here so we can explain what's going on so the db set property will tell ef which is entity framework core that we have a table that needs to be created if it doesn't exist great so once we have done that now what we're going to be doing is we're going gonna be creating this actual database and creating this table inside this database so how do we do that so we're gonna be utilizing some uh entity framework tools that we have installed earlier and basically from inside our terminal we're gonna do two commands which is basically first which is gonna be set up uh prepare all of the required setup for the database and second it's gonna be executing that setup so the first command we're gonna be today utilizing is the netf migration so we're going to put dot nut which is basically referring to the sdk ef which is referring to entity framework and here we are actually utilizing the tool that we have installed earlier and now we are adding the command which is migrations or with any entity framework to create a new migration which basically new sql script that's going to be applied against our database and then we're going to put the word ad because we're creating one and we're gonna give it a message which basically what changed uh inside this migration and right now we're just gonna do this is initial migration because we don't have a database we don't have anything so it's gonna be the initial migration and as well we're gonna say adding the user class the user table great so once we have done that we click on enter and just take a few seconds and let's monitor here what's happening we're gonna see right now a new folder popping up which is called migrations and if we open this migration folder we can see here that we have two things three things sorry we have uh some numbers and then initial migration with the message that we have added as well we have something called the application db contacts model snapshot so the application db contacts model snaps would basically represent a copy of what information exists in the database so it will give for me it will have information about which table does it exist does it contain what are the rows and the fields of every table it's just like a scheme of the database is saved inside the application db contacts model snapshot basically all of the schemas are saved here you know because every time we create a migration a comparison will happen between the application db contacts the model snapshot as well as the change that we have made and the difference between these two schemas are basically the migration scripts that's being created in order for us to update the database to the latest version of the change that we want so here if we open this we can see right now all of the changes that we wanted to do which is basically here we can see that we have a new table called user and basically it has id which is of type text email first name and last last name and we can see here that it has the command of create table and it gave it the name users and we can see here that the ids of type good uh first name last name and email of step string and everything is nullable except id which is what we expect as well as it specified the primary key which is going to be the id because entity framework will automatically take the id keyword of every properties as a primary key great so once we have done that now the next step first is to actually create the database and actually apply this migration so because we don't have a database entity framework is going to create it automatically for us and apply all of these changes for it so let's monitor what's going to happen here first inside our terminal we're going to type not ef database update and this keyword basically the dotnet very first.sdk entity framework refers to the entity framework tool we're specifying whether we we're telling the entity framework that we have a command for the database and the word update means that we want to apply all of the changes that the migration has created if there is no migration no migration will be updated so let's click on enter and just monitor what's happening here so this should take up to a minute and now we can see that we have a new database created which is called app.db and we're going to open this app.db and check what's inside so in order for us to do that we're going to be utilizing db beaver which is a free tool that will allow us to utilize and view the database so now we're going to click on this icon here and we're going to be utilizing sqlite so we click selected and click on next and then we're just going to browse to it so we're going to go to desktop youtube pocketbook and i have db context then open this test connections make sure it's okay and click on finish and once that we can see that our application is here and once you open it and we go to tables we can see that we have the tables user that we have created and if we open this by view data and we go to properties we can see the four properties that we have which is id first name last name and email great so let's go back now to our application and we're going to be starting right now by creating our repository so inside the root directory of our application let us create a new folder called core and inside this folder we're going to create another folder which is called i repositories and inside the app repository we're going to create our first interface and this interface is going to be the most generic interface that we're going to be utilizing in order for us all other interfaces are going to inherit from so we're going to create i generic repository and we're going to be clicking enter and now we have an interface inside the eye repository and inside the core folder so basically what we're going to be doing is we're going to be creating generic repositories and then we're going to be creating specific repository which is going to be inheriting from the generic repository that way we're going to have the same commands available for every repository and if there's any repository that's going to have its own unique command it can add it independently of instead of having it across all and this way where i can actually utilize and have the drive model there so we can create the code once and we can utilize it everywhere so once we have added the interface now now we're going to start building it so the first thing we're going to be doing is because we're going to make it generic we need to add the t keyword and we're going to say where t is a class perfect and once we have done that we're going to specify that the six uh methods that we want it's gonna be first of all task because it's gonna be an asynchronous request and we're gonna utilize the i innumerable and then we're going to return a list of t based on the class and it's going to be called all now let's fix those references perfect so the next one we're gonna say is cut by id so task and we're gonna return t that's gonna got cut by id and right now it's going to be the idea of type code and here that's your system great next we're going to doing the add which is going to return a boolean so tax bull and it's going to take basically the type t then we're going to add task for the delete sorry we're gonna return a boolean and it's gonna be delete and it's gonna take the code id and then we're going to do the upsert which is going to be task pull and we're just going to do the opposite and it's going to take t and then we're going to call it entity perfect so now we have these five uh methods that we're going to be utilizing and this is as we said this is going to be the generic repo now we need to create a specific for the users so how do we do that inside the eye repository we create another interface and this interface we're going to call it i user repository so once we have created this i use a repository we're going to be utilizing the i generic repository so how do we do that if we said inheritance that's correct so we'll come here and we're going to inherit the igeneric repository and we're gonna pass the user's entity to it and that way the user here is gonna replace the t model here whenever we're gonna be utilizing this generic repository great so as i said here these are all of the methods that are going to be utilizing all across all the repositories so let's say we have a car repository we will will inherit this i generic repository as well we can add different types of methods related to the car inside the car repository so right now for example let's say i want to get the first name and last name of the user and we have uh the let's say we have the car repository and we have the user repository it does not really make sense to add here the method of get first name and last name of the user because the car does not have a first name and the last name so it does make sense actually to add it in the eye user repository so in case i want to add that all i need to do is here tasks and i can return a string for example and here it's gonna make got first name and last name for example and it's going to take a good id and basically right now i created the new method generic method uh sorry a specialized message for a user repository which is not going to be available for anywhere else whereas every method in the igeneric is going to be available for every interface or any repository that's inherited from it okay great so now that we have covered those so we don't really need that method right now but uh once we have created the i user repository now it's time for us to create a unit of work which is basically the interface for the unit of work that we're gonna be utilizing and inside the core folder we're gonna be creating a new folder which is going to be calling it the i configuration and i think you can tell right now that everything that we do within the uh unit of work pattern as well as repository padding is all based on inheritance and interface and classes so once we have created the i configuration uh folder we're gonna actually uh create the i unit of work interface inside of that so let's create a new interface and we're going to call it the i unit of work great so once we have created the unit of work and this interface basically is going to have all of the repository that we're going to utilize so right now since we only have 100 which is called the user repository i use a repository so we have to add this here as well we're going to add another method called complete async which is going to be responsible of communicating all of the changes that we added to our entity framework and repository to the database so first we're going to just add the first repo which is a user interface sorry yes i use a repository and we're just gonna call it users and we're gonna specify the gutter for it here and let us define fixed references and then we're just gonna create a task for a method called complete async and this complete async is gonna be responsible for actually uh sending the changes back to the database great so let's fix this so now that we have created or started created the skeleton for our unit of work now it's actually time to start doing some of the work for the actually filling the repositories work so how do we do that so we need to create a repository folder inside the core folder so as you see here we have the interfaces now we need to create the actual implementations for it so inside the core folder we create a new folder we'll call it repo series sorry not a file a folder [Music] let's copy this and let's delete this and yes move to trash thank you and here new folder and just paste it perfect so inside the folder here we're going to be creating that generic repository so we're going to create a new class and this class going to be the generic repository implementation okay great and as we did for the eye generic repository we need to make it also generic so how do we do that we're doing the same thing so let's go here and let's first add the t to make it generic and then basically what we're going to be doing is we're going to be inheriting from the i generic repository so we can enforce all of the methods that we have inside the generic repository and we're going to pass the t because it's also generic and we're going to specify that the t is a class and now let's fix these references great so once we have add that we still have the squiggly line here because we have not implemented all of the methods that this repository requires so we're going to start by doing that the first thing we're going to be doing is we are going to actually adding the application db context so from here it's going to be protected and it's going to be the application db contacts because we're going to be utilizing it and just we're going to call it context and let's fix these references great so the next thing is we're gonna make it internal or we're gonna make it protected doesn't matter here and because it's a dummy application we're gonna call the dbsat t and we're gonna call it dbsat also let's fix these references and lastly let's add the logo so let's also make it protected and make it read only make it i logger as logger and let's fix these references perfect so once we have done that now we need to start initializing it by initializing the constructor so first we're gonna be initializing the application db context and it's gonna be underscore context and then we're gonna be initializing the logger so i logger logger and then basically it's gonna be underscore context equal contacts we're just doing all of the required setups for the dependency injection for it to work because right now the application db context is enhanced added to our dependency injection because we have automatically wired up inside our startup class with this because we have added here the rdb contacts it will be available for us inside our let's undo this here so it will be available for us inside our dependency injection framework so we don't really have to do anything else so and this is how actually we are able to inject it uh through the class that we are currently utilizing through dependency injection so we have already added the contacts and the locker is automatically provided for us by the entity framework sorry by the asp.net core so now we're just gonna be utilizing it logger logger and save this and now let's click on here and let's click on implement interface and as we can see we have the five five methods has automatically been created for us and we can actually utilize them so the first one we're going to be doing is the get by id so we don't really need that let's delete it and basically we're gonna just do a return await dbsat dot find async by id so that's the generic repository but we are we're gonna be able to change it later and here we're gonna make it async because we're utilizing awake oh wait sorry in the next step we're gonna be utilizing the add and also let's add the async from now let's delete this we don't really need it and now let's actually add the functionality which is gonna be await dbsat dot add async and it's gonna be entity save and then we're gonna put return through because it has to return it through a boolean sorry so once we have done that now let's do the delete uh what we can do actually so we can uh see how it's working we're gonna just leave it as uh not implemented so we see if actually we don't implement it what's gonna happen uh the observed we're gonna do the same thing and for the all we're just gonna return everything so what we're gonna be doing is return let's here make it uh async and we're gonna make a dbsat dot to the stay sync and basically we're gonna be returning everything and we need to await it great so once we have done that and we have created the generic repository now for us let us continue by rebuilding the user repository that we have added so we have added here the i user repository now we need to add the user repository here so we're going to get a new class and this clue class general could be called user repository great and this user repository is going to follow the same structure as the generic repository but instead of inheriting directly from the i generic repo we're going to inherit from the generic repo and then from the i user repository so we can have both of them here so user repository we're going to inherit from the generic repository we're going to specify that's going to be of type user and we're gonna also inherit directly from the i user repository in case we have extra method that is not part of the generic repository the iuser repository will be provided for us so let's fix these references and now we're having issues okay so once we have added that we actually start need to implement this so the first thing we're gonna be doing is we're gonna creating the constructor and inside the constructor we're gonna be initializing the db context so we're going to be passing it back to the parent class which is the generic repository and basically we're going to be doing something like this application db context context let's fix this reference and the logger so i logger logger and let's fix this and from here basically because we are inheriting from the generic repo we need to pass it back to pass it back to the base and we're gonna pass the context and the logger great so once we have done that we can now actually start implementing some of the method that we want and we're gonna be basically implementing the all absurd as well as the delete because that it's very simple we don't really need to override it so let's start first by the all and how are we going to do that we're just going to be making it public and because this method already exists in the parent one in the generic repo we're going to override it so we're going to utilize the override keyword and we're going to be utilizing the async because it's going to be async method and basically we're going to return a task of i innumerable and it's going to be we're going to turn the list basically of users and we're gonna call it all if i can type they okay great now let's fix these references so once we have done that the next step for us is to create a tri-cuts so in case something goes wrong we are able to do grace for error handling and let's fix this and basically here all we're gonna be doing is return await dbsat dot to list async and in case something goes wrong we're gonna just add it to the local so we're gonna say logger dot log error and basically we're gonna pass the exception and then we're gonna build the message we're gonna call it here repo because we're gonna pass it and we're gonna say which function which is all method error and then here we're just gonna pass uh the class name and we're gonna be testing the type of oh apologies this should not be here yes so this should be type of and we're gonna make a type of user repository great so the next step is because it has failed we're gonna return an empty list so we're gonna put return new list of users which is gonna be empty okay perfect still telling us that we have an error i wonder why so return list await async and see what's the error cannot override inherited number okay let's go back to the generic one and we forgot to add the word virtual because we want to enable overridden so this is going to be virtual okay great let's save this and let's go back here and it's not complaining anymore perfect so once we have done that the next one we're gonna be is updating is the absurd so public override async it's gonna be a task and it's gonna turn a bull and it's going to be upset and the user entity and basically we're going to look for this user base on its id if we find that we we're going to update it if we don't we're gonna add it so var is it's gonna be an existing entity existing user equal await dbsat dot where we're gonna adding here the conditioning for this so we're going to be utilizing where which is going to be based on link and then from here we're going to add the condition x x dot id is going to be equally equal to entity dot id and then we're just gonna get the first or default so dot first or default async and then that's it so right now we're actually going to the database checking if there is an id which must the id that the entity has and we're returning the first result if it's not returning or not so now we're gonna actually do the check if existing user equal equal to null so it means it doesn't exist the id and the user does not exist we're gonna be adding this information to our database not updating it so we're gonna put return we're gonna call the add method and we're gonna pass the entity to it great but in case it actually exists we'll just need to update it so we're gonna put existing user dot first name equal entity dot first name it's gonna be existing user dot last name equal entity dot last name and then lastly it's gonna be existing user dot email equal entity dot email and then we're gonna put return to true perfect now that we have done that we forgot to put it inside a try-cat so let's do this now actually yeah let's put it this now and then so try it catch and as we did before it's gonna take an exception the axe and basically it's going to be the same thing as the add so let's take this and we can adjust it here so instead of all it's going to be upset absurd and here it's going to return false in case it fails and let's take all of this code here and let's put it inside the try okay i wish visual studio code has better code indentation for c-sharp anyways so once we have added the upsert now we're gonna add the delete functionality so after this method here we're gonna add the delete and similar to what we did before it's gonna be public we're gonna override it and it's gonna be async and we're gonna be returning a task of bull and it's going to be delete and we're going to pass the id that's a good the first thing we're going to be doing is add the just copy this and let's paste this here and here instead of upset it's going to be delete and that should be the same and now let's implement the delete functionality so basically the delete function is going to be the same thing as abs the first part of the absurd so far if it exists equal await db set dot where and then we're gonna be matching based on the id and then once we have done that we're just gonna do the first of default and based on that now we're gonna check if it exists we're gonna delete it so how do we do that we're gonna just put dbsat dot remove and we're gonna pass the exists and here we need to make it not equal to null and then let's add brackets we can add the conditionings as well to return true and we can put return true but if it doesn't exist we're just gonna return false so we're gonna put return false so basically here we're checking if the actual uh i if the actual entity exists based on the id if it does which is mean this is not null we're gonna remove it and then we're gonna turn through if it is uh if it doesn't exist we're just gonna turn false perfect so the next step after that is basically now we need to link the uh a unit of work interface that we have created before with the unit of work and do all of the pipelining and all of the wiring for the unit of work and the repository framework to work simultaneously together so in order for us to do that we're going to create a new class inside the data folder and we're going to call this unit of work great so once we have created this unit of work class the first thing we're going to be doing is we're going to be inheriting directly from the i unit of work interface so we can see all of the available unit of all of the available repository that we can utilize and then we're going to be also utilizing the idisposable interface so we can actually dispose of our and our db contacts safely so using system and here we're going to fix those references great so the first step is we're going to be defining the contacts on the logger so let's make it private i think it's better uh let's make it read-only and we're gonna put the application db context and again we're gonna inject this because we're utilizing the dependency injection and then similar private it's going to be read only and it's going to be the i logger and then once you have done that let's fix these references and now we're going to be utilizing the only repository that we have so it's going to be public a user i use the repository and then we're gonna call it users similar to what we did inside the i unit of work and basically we're just gonna put the gut and the private set which we can actually utilize we can actually update to use the uh and it only settles that sharpness provided for now we're gonna keep it as a private set let's fix these references so once you have done that we're gonna be initializing the constructor now so and first of all we're going to pass the application db context and it's going to pass the i logger factory because from the i logger factor we can create a logger great and now let's initialize them inside the constructor so as we said before context equal context all thanks to the dependent interaction and it's magic and then logger equal logger factory dot create logger and we're gonna call it logs perfect once we have done that now we can we need to do the wiring between this interface uh uh the user repository interface and the user repository that we have created here so how do we do that it's very simple we're just gonna put users which is basically referring to the user repository interface equal new user repo and we're gonna pass the required contacts on the logger and let's fix this reference great so now we have initialized uh the repository we have linked the interface with the actual class and after that we need to add the the other method that we have added which is the complete async so we're gonna put public ac async and it's gonna be of type task because we're not gonna return anything from it and this is going to be complete async and now let's fix this reference here and here all we're going to do is we're going to add one command to the database which is going to be the save changes and this saved change is going to take everything that we have already done inside our in memory database and all of the change that we have done and it can actually reflect it inside the database so save changes async and the last method that we're going to be having here is the dispose method and we're going to be accessing it through the eye disposable so it's going to be public void dispose and basically this method is only going to be the spotting of the contacts the contacts that dispose async and that's it so basically whenever we're not using it anymore it will be disposed properly from the garbage collector great so let's do it let's make this async and so the void let's make it a task so perfect let's see here oh we need to also implement the non-async one let's remove the async one for now we can manage it later okay great so now once we have done that now what we need to do is let's do a quick summary first then we can discuss what do we need to do so what we did first is we have created the folder core and inside the code we have created the i repository folder i was going to contain all of the repository we have created the igeneric repository which contain the main methods that's going to be available for all of the repositories and right now we only have one so if you only have one you don't really need to do that but because uh we're gonna have a lot of different repositories uh in future projects so for now we just had added uh added one so we have accredited the eye generic repositories and then we have added the i user repository and we have inherited from the eye generic one and then we have build the eye configuration which basically tells uh define of how the unit of work is going to behave and said we have only have one repo inside this unit of work called users and we have added this task which can be responsible for communicating that changes to the database and then we have added the repositories which actually are the implementation of the interfaces and basically what we did is we have initialized the db contacts and the loggers and we basically did the implementation for them in the generic one and then we have override them inside the repositories uh user repository so we can make them more customized to the actual users table and once we have done that inside the data folder we have created the unit of work which inherits from the eye unit of work interface that we have created earlier and the id is possible in order for us to utilize the garbage collector to clean our db context once we have done that we have initialized the db contacts and the loggers and then we have different defined repositories that we have which is the user repo inside our constructor we have initialized the db contacts and the logger and then we can actually initialize the custom user repository that we have created within and then we inject it to them that the application db context and the logger and lastly what we did is we have added the code so we can update all of the change the changes that we do that we do in the in the memory to the database and actually disposed of the contacts properly using the context.dispose okay so once we have done that now the application with all of this work the application still doesn't know what to do with it because we have not added to the startup class so the next stuff the next step is for us to inject all of these changes inside the startup class so inside the startup class what we need to do is inside the configure services method we're gonna add the following so services dot add scoped and basically we're gonna be using a unit of work and unit of work and basically what we're doing is we are enable dependency injection of the iunit of work to anywhere inside our application so in case we need to utilize it anywhere we are adding a scope version of this unit of work so it will be available within the di container great so this is the step so here we just saw the command adding the unit of work to the di which is dependency injection container great once we have done that the next step first is just create our controller so inside our controllers folder we're going to create a new class and this class is going to be called users controller very simple users controller and inside this user's controller we're going to actually start defining our controller so it's going to be also very simple so the first thing we're going to be doing is we're going to be adding some attributes to this class so we can make it an ad a api class so how do we do that the first one is going to be api controller the next one is going to be basically the route for it and basically we're just going to utilize the controller's name let's fix this see this we don't need these components we don't need the components we need the other one okay so once we have done that now what we need to do is we need to inherit from the controller base which is going to give it all of the um minimum requirement to be an api controller so we have done that the next step for us is to initialize the logger and the i unit of work so first of all we need to declare them so private i mean convenient only the i logger for this class and we're gonna call it logger and then private read only a unit of work and it's gonna be underscore unit of work and let's make this let's make this here fix this references okay great once we have done that now let's define the constructor so we're gonna first define the i logger of users controller and it's gonna be a simple logger and then the i unit of work is going to be unit of work and then basically after that we're going to be defining them so as sorry linking them so logger equal logger and underscore unit of work equal unit of work so before we do anything else let us build this application make sure everything is still building so that not built and this should take a few seconds great the bending is still winning successfully so the first thing we're going to be doing is we're going to be adding the ability to create a user because we want to create stuff before we are able to see them so for this reason we're going to start by the create and this is going to be acquired we're going to create the all create edit and delete so the first thing is going to be creating a user which is going to be an http post so we add the attribute http post and then once we have done that we're going to add make it public async task of i action result uh we're gonna call it create user and all it's gonna take is user for now there is way better ways to do it which is going to create a dto what this can be for later video for now we just want to test if the functionality is working or not so let's add fix these references perfect so once we have done that first we need to check if the model state is valid so model state that is valid and the model state mean if the anti if the model that we are currently utilizing is a valid model so if we added any conditions to the model for example let's go to users and for example for the email uh if we added for example an attribute saying an email this field needs to be an email it's not it doesn't need to be only a string so for now if i pass an object for example it's going to be i'm at i'm not for example uh any string it will pass because it doesn't have email verification but if i add that attribute email and if i add any string on the object and i send it it will fail because it doesn't match so that's why we use model state that is valid so next we're just going to generate a an id for the user so user.id uh as you remember the id is a good so we're going to be retrieving the grid dot new grid and we need to fix the references for the grid and then once that is done we can see here right now the power of unit of work so all we need to do is await unit of work dot users.add and we're gonna add the user and now we need to commit the changes because the first one adds it into the server's memory the second one actually send the changes to the database so it's gonna be complete async and that's it so basically right now we only have two lines of code which actually gonna do all of the database work so let's now continue this so in cases successfully we need to follow the last api uh right implementation so we need to follow that created that action and we're gonna go to the get item we're gonna it's not there at we're gonna create it and we're gonna pass the objects for it for it's gonna be the user id and we're gonna pass the model of user so again this doesn't exist yet we're gonna create it afterwards and then lastly in case uh something goes wrong we're just gonna be returning a json result of something is wrong let's fix this reference return json oh sorry i forgot the word in you and let's add a http status code of 500 so the user able to know that something has gone wrong and let's put the semicolon okay great so this is for the created user let us try it out so let's build it first not build perfect now that has built successfully let's run it dot not run great now we're going to be utilizing um insomnia in order for us to test all of these so let's open insomnia so inside insomnia let's create a new request collection we're gonna call it uh pocket book v2 and then basically we're gonna be creating a new request and this request we're gonna make it uh called create user and then we're gonna make it a post and i'm going to click on create and now we need to pass the domain which is going to be let's use this one https that's fine and basically right now we need to pass the body and as we said it's gonna take user so first name last name and email but because we don't wanna pass the id because we're gonna generate it we're gonna just pass those so inside body here we need to choose json and let's fill it up so it's going to be first name let's make it as muhammad last name it's gonna be lawand and email is gonna be muhammad.email.com and now let's send this and see what happens so we got a 404 oh because i didn't specify the route i apologize for that so it should be users let's send it again and we said okay we have an error let's see what's the error so we can fix it so it says on the object reference not set okay on the ad on line 38 generic repositories line 38 let's see what's the issue okay so let us debug it so let's go back to the user controller let's put a breaking point here and let's stop this and let's use the debugger inside the studio code okay great now let's go back to insomnia and let's send this request again and we should receive it here great so let's jump in see first of the information are coming true so muhammad okay great now the id should be automatically generated for us let's see this one great unit of work user add great and now it's failing okay let's send it again and see what's happening send and now let's right now let's go inside this so it's going here the entity is being pulled successfully users great and it's failing okay so the issue is we forgot to initialize the db sat inside our constructor i apologize for that so how do we initialize it it should be very easy so it's going to be dbsat equal context dot sat which is basically we're sending the contacts to no matter what class it is and that's it now let's try it again and we think i'm confident enough to write without the debugger so let's try it great now let's go to insomnia understand the request i do apologize for this so the issue was here uh the first of all we did the wrong referencing so it should be underscore context then equal to context one initializing and that second that we didn't initialize the db sat we i forgot to initialize it when i was doing the generic repo so we just needed to add that db set equal contacts to set to t so that should be it and now if we try it it will fail because if we go back to the user repository we're actually referring back to a new sorry to the user controllers we're referring back to this action which doesn't exist so let's create this action so after this we're going to create a new method it's going to be got http got and it's going to take an id and then we're gonna put public async task of i action result and we're gonna call it get item and it's basically gonna take the guide as an id great so what are we gonna do it's very simple but we can utilize the unit of work we're gonna call it user equal await underscore unit of work dot users dot cut by id and we're gonna pass this id and if user equal equal null we're gonna return the not found which is basically going to return a 404 status code and then basically if it is there we're just going to return on ok with the result okay let's run it again so let's go back to terminal and let's go to let's do i clean up first and run perfect now let's go back to insomnia and let's call this for example mickey mouse uh let's call this mickey at email.com understand this and we can actually see that we got the 201 status code created we got the id the first name last name and the email perfect so once we have done that now let's create a new request which is going to be basically get user by id create it we're gonna take the same thing let's take this url let's paste it here and basically after that we're just gonna be passing it the id so for the slash so let's take this id to test it out and there's nobody there's no anything i was just gonna send it and we're getting the information correctly with a status code of 200 perfect now let's change one of these numbers to one from it to we should get a 404 perfect four for not found if i change it back to one send 200 okay great so now we have the get the get users and the create user now let's see get all users so to get all users going to be also very simple it's going to be a http gut public async task i action result and we're just going to be i got a simple gut and basically we're going to be writing var users equal unit of work dot users.all that's all we're going to be doing i'm just going to be returning that back to the user so i'm going to be turning ok and users perfect so let's stop this application understand it again once we have done that let's go back to insomnia and let's create a new request and we're gonna call it got all users and it's also gonna be i got so create let's take the same domain don't really need that id because we're getting all of the users and now let's send it and we can see we got the two ids that we have the two users that we have muhammad admit perfect so now we have got got all and create so we still have two to implement which is the delete and the update let's start with the update first so let's go back here so the update because we're going to be changing something to the database it's going to be of type post so http post and because we need to verify the id that we're going to be sending it so the extra ester level of security we're going to adding id and then from here we're gonna put public async task by action result update item we're gonna call it uh we're gonna take a good which is an id coming from the url and we're gonna be passing the user's information great and what we're gonna be doing is the first check if the id is not equal to the user.id we're gonna refuse this so we're gonna return a bad request if it actually matches we're gonna await underscore unit of work dot users dot upset user await underscore unit of work dot complete async and after that we're just gonna be returning because it's an update or support we're gonna put a return no content we're not going to turn anything back because basically this is the last standard for doing any updates so let's try this out let's stop this let's run this so let's create a new request we're gonna calling this upsert user so gut okay we're gonna make it a post so the body is going to be json let's take the same one from here we can just add it and let's paste it and let's take this id and let's add it as well so let's take this and let's put it here so i need the url with that id and this id needs to match this id okay now let's change the information from eq one mickey mouse one and the making one email let's see if it's gonna update i click on send and we got a 204 no content which means it got updated successfully now if i click on all users and i click on send we should get mickey one mouse one and make one at email and we got it perfectly so now we have the update working as it should lastly we're gonna be adding the delete let's stop the application so now let's interpret the the delete so because it's a date we're gonna implement the http delete attribute and we're gonna pass the id then we're gonna be adding public ac if i can type async task i action result delete item uh make it as good id great we're gonna make var item for item equal awaits underscore unit of work dot users dot get by id and we're going to pass the id so in case this item exists so our user exists so if item equal equal null basically we're going to return that this is a bad request because it doesn't exist and because in case it doesn't exist we're going to delete it how are you going to do that then it was going to fork so await you need to forks users delete it's going to take the id then we need to commit the changes to the database unit of work complete async and lastly we're just gonna return the object so return okay and we're gonna return the id save and let's try it out so let's stop the application and let's run it again let's create a new request so new request we're gonna call it delete user and it's gonna be of type delete create let's get uh domain so we're going to make it this and let's put this here and we need to add the id the id so let's get all users and let's get the id of mickey and let's add it here and now let's see if this will work so send and as you can see we got back the id we shouldn't get back the id we should return the new item okay let's stop it and let's run it again let's go back to insomnia let's create a new user and we'll call this one for example donald do not okay doc and let's call it donald okay let's create this and get all users we should see donald here great now let's take this copy now let's do the delete and add it here and now we should see the information of donald here all available instead of the only id send perfect now we see the id first name last name and email great so that's a quick summary so what we did first is we created the uh core folder with the i configuration sorry i use i generic repository then we created the user repository where we defined all of the methods that we have then we added the configuration inside the add unit of work then after that we have started building the repository inside the repositories folder once we have done that we have added the unit of work inside the data folder and then we configured them here we have added all of the mappings together once that was done we updated the startup class so it will take full advantage of the unit of work and will be able to utilize the dependency injection container and so we can inject it inside our controllers then we have created our controllers and we implemented the crowd on the users so that's a very simple approach to unit of work there's a lot of more details that we can jump into please feel free to ask any question in the comments down below as well as any other topics that you'd like me to cover one thing i would like to mention before i go so here inside the user's controller for the upsell it shouldn't be a post here it should be a http patch so that's uh the the correct attribute that we need to utilize at http post so uh other than that thanks again for watching please like share and subscribe if you like this video it will really help the channel and have a great day
Info
Channel: Mohamad Lawand
Views: 55,878
Rating: undefined out of 5
Keywords: beginner guide, step by step, csharp, c#, C# 9, dotnet, repository pattern, dotnet 5, unit of work, uow
Id: -jcf1Qq8A-4
Channel Id: undefined
Length: 89min 51sec (5391 seconds)
Published: Thu Jun 17 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.