.NET 7 - Build CRUD with Web API / EF Core / Repository Pattern 📚📚📚

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
foreign thank you for watching this video I am Muhammad and last week Microsoft jlist.net7.net7 abroad without a lot of new enhancements bug fixes new features as well out of performance gains so in order for us to celebrate this I have a created the.net7 course specifically in web apis taking you through the entire process of creating different Cloud operations connecting to a database implementing unit of work so on so forth so if you like this video please like share and subscribe it really helped the channel as well if you'd like to support me please consider supporting me on patreon or buying me a coffee now grab your cup of coffee and let's get started we're gonna start first by exploring what is new in.net7 we're going to be seeing basically the new features then we're going to be seeing how we can actually install.net7 hour machine once we installed that not seven hour machine we're gonna be seeing how we can create our application and basic start implementing our full Cloud operation with Entity framework seven so what I did here is basically I went to the release block of dotnet7 where we can actually see that there is a lot of new functionality that has been added so here we can see within this block form they can tell us basically what is new within.net7 and one of the main two things that we really want to focus on is basically the asp.net core 7 release as well as the Entity framework core 7. on top of that there is multiple other upgrade to the nutmavi to Windows Form to not only and so on so forth as well as the new c-sharp features but for the sake of this video we're going to be focusing basically on asp.net core 7 and Entity framework core 7 and any other any other feedback or basically any other new features that you want to explore please put it in the comments down below and maybe I can create a video about it later on so let's go to the asp.net core 7. and here we can see basically some of the main new implementation or some of some of the main new enhancements like rate limiting request decompression HTTP 3 minimal apis enhancements grpc signal or mvmvc so on so forth so we're not going to be really implementing all of these new features uh we're going to be basically further First Step we're going to be implementing like a basic Cloud operation where you're gonna be updating all of the many Cloud actions and then we're going to be able to connect it to our database through Entity framework core 7 and this is going to be like a stepping stone then we're going to be implementing based on that within the next video maybe we're going to be basically adding more functionality into that we're going to be maybe implementing rate limiting we're going to be adding some more functionality based on the new functionality that has been implemented within.net7 so now let's take a look at was well what is a new and Entity framework course oven and within this Entity framework of course I mean we can see that some of the main implementation of some of the main features is a table per concrete type TCP TPC mapping so on so forth there's a lot of new and exciting functionalities that's coming within AF core 7 which can be basically allow us to have a much more better rigid unstructured a DB experience so I think Richard is the wrong words with a more structured I think that's better so and there's a lot of box fixes when it comes to f47 which is really really important so once we have done all of that and basically once you have read all of the new releases when it comes to Entity framework seven um basically the next step for us is we need to actually upgrade to note 7. so how can you do that all you need to do is go to download but not and basically once you go there you will be able to see that you're gonna have two types of download so not right now comes in two flavors there's gonna be the current version and the LTS version so the LTS version mean is gonna be a long-term support which means that this dot-not version is going to get all of the security updates and all of the fetches for the next two three years actually three years and because uh it's it's a much more stable support So if you're trying to build like an Enterprise application it's much better always to have an LTS version rather than have a current version because you know all of the security updates is gonna come to that version until the end of life on the other hand the current version it basically have all of the latest and greatest functionality.net frame that does not has to offer it has all of the latest changes that every year is going to be released is it has all of the area security patches but the main downside within that is basically once it reached its end of life which is usually one year you have to upgrade to the next version because it will not get all of the latest security updates so here you need to see what is the the best implementation for you and for your application and for your all organization do you want to be on the latest version then you need to go with the current one do you want to be on the most stable one with the get the latest security updates that's going to be the LDS for the sake of this video we're going to be downloading the latest one which is calabito.net7 so and here we can see that it says standard support term support and we can see here that it has a long-term support and we can see as well that uh both of them are available for us to download and all of them support different types of operating system like the support Windows Mac Linux and even support harm so it's going to be the amount chips so here also we can see some of the new additions.net7 we're not going to go into this right now so once we decide you can click on download and we can see that you can download the.net SDK 64 on arm so that's what we want what I'm going to be doing as well another way we can actually upgrade is basically upgrade our home room so right now if I go to my terminal and I type.net dash dash version I can see that I have the latest which is 6.0.402 but if I type Brew upgrade now this should upgrade my.net version 2.7 and this should take a few moments to complete a few moments later okay so now that the upgrade has been completed and basically now if I order do.net version I should be able to see that I'm running on top not seven so let's see again not dash dash version and here you can see I'm running on the latest version which is going to be version 7.0.100 perfect so now what I'm going to be doing is I'm gonna be going through uh Rider and I'm going to be creating actually what we can do is I can create a new web API through the command line and then actually utilize Rider to open it and edit it so 4.7 you can use for example Visual Studio which has been released for the latest support 4.7 it does contain all of the new features you can utilize Visual Studio code as well you could you can utilize Rider there's a lot of different tools out there that you can actually trust the creator.net application for the sake of this video I'm going to be utilizing Rider but please feel free to utilize anything and you are on Windows you can use Visual Studio on Windows which is 122.4 which has the full support of all of the new feature that note 7 has to provide so now let's go to desktop work learning.net I'm going to create a new folder I'm gonna call it not 7. and then from here I'm gonna just create a new dotnet new web API and I'm gonna call this one a let's say formula API and that's it that's all we want to do perfect now I'm gonna open Rider and here I'm going to click on open work learning .net 7 formula API and then open my formula API yes I do trust perfect now my application is building we can see here I does not have full support yet but that should be fine and now if I open this let us first so now that our application has been created 10.7 first we're going to be exploring the solution a bit we're going to be seeing the different uh changes basically there's not going to be a lot it's all going to be a change in the Cs approach and the packages and from there we're gonna actually start by creating our models so on so forth so let's check our CS approach and then here what we're going to be doing is edited and we can see here that the main items that are changed which is going to be the target framework and the target framework here is going to be.net7 on the other hand if we look at any other application let me open on your other application let's see the formula Airline for example new window so this one this was an old application for an old video but if we take a look at the Altius approach okay where is it we can see that the main differences here is this let's put them side by side so it will be easier for us to see let's close this we can see here that in the new one we are targeting.net7 Target framework and then the old one we're targeting.net6 and that's all it is all we need to update if you're upgrading from.net6 to Note 7 is just update the target framework update the packages and then you should be ready to go and as simple as that the applicator is done there's not going to be a lot of major changes like moving from.net500.6 where the basically the entire startup class has been removed there's none of that in.net7 when you're applicating from.net6.7 make sure you are targeting the right framework and then updating those packages so now this is be fine we don't really need this anymore and the first thing that I'm going to be doing is inside my terminal I'm just gonna type dot not build to make sure that my application is building successfully exactly the perfect that's exactly what you want and now let's start by uh cleaning up this a bit so first of all I'll only need this anymore the other controller so let's delete this and it's going to create issues here in my controller which is fine I don't need this just doing some tidy up and here I'm just gonna be returning a I action result and here we're just gonna be returning uh let's just return okay I don't need this and that should be it so if I do not build okay great so the first thing that I'm going to be doing is I'm going to create a new folder a new directory and I'm gonna call this models and inside is my model folder I'm going to create my first class or actually first model I'm gonna call it drivers so what's kind of do I what's gonna what's what type of properties my driver is going to have it's going to be very simple first let's put uh we're gonna give it a string as name oh let's put the ID prop and ID let's give a driver's number and then end and just put also the team that they race for team very simple okay so now that we have our drivers models basically what we have here is we have created a very simple model which can be representing an entity inside our database and this model is called driver and test for properties ID name driver number and team it's a very simple implementation so once we have done all of that the next step is we're gonna be going to our controllers and I'm gonna create a new controller I'm gonna call the drivers controller and basically here we can see that the Contour has been created first of all I don't want to utilize the entire controller so I'm just going to utilize controller base which is a simple version of that I don't need this I'll add it later so first things first what I'm going to be doing is right now I'm going to be creating an in-memory database a sort of different actions that we have that got post patch and delete we're going to add those we're going to be experimenting with them and within this MML database once we make sure that they are running what we're going to be doing is we're going to actually create DB context and once we get our DB contacts we're going to be updating our controller to utilize this as well once we have done all of that we're gonna have actually experimenting with it so maybe we're going to add more services to it so let's see how this will go so first things first is let's create this first memory database so it's going to be a public sorry let's make it private actually let's make it private read only and it's going to be a list of driver and I'm gonna put drivers equal a new Drive list of drivers and just to make this a bit simple and much more easier to do I'm gonna be creating default drivers as soon as this application is created we're gonna have a few drivers there so the first driver is going to be of course uh Lewis Hamilton so Lewis team is Mercedes AMG phone and driver number it's 44. and then we're gonna add another driver new driver ID equal to name equal George Russell same team congrats George on winning your first Grand Prix Mercedes AMG F1 and driver number is 63. let's add another driver it's going to be new driver and which the star is going to be let's see okay let's put ID equal three name Sebastian Vettel Sebastian driver number I think it's five and the team it's the Aston Martin well now we have that we have created this the first one we're going to be doing is the HTTP get and basically here we're gonna put public I action results I'm gonna put get so I'm gonna take anything and all we're going to be doing is return okay and we're gonna return the driver's list as simple as that so this is a very simple API directly we just got the database from in memory and we're gonna be drawing it out build and then all I'm going to be doing is I'm gonna say dot not run and let's open this foreign Swagger Force inductor HTML perfect okay it's only only have one of them why if we don't have the second one okay when we created this we did not add all of those different specifications to make sure it's an API controller so let's add these now let's just stop this under it and run it again and now we should be able to see it so let's see fresh perfect and now if I do it right out I execute I should be able to see my three drivers available for me perfect so now that we have created our first action which is going to be the get the next one is going to be get by ID well we're going to be passing an ID and we'll be able to get the results that we want and then after that we're gonna be adding them so it's going to be a post and the one after that we're going to be deleting them so let's take this into and let's see how this is gonna work just make sure this is in the right frame okay perfect so now let's go back to Rider and now we're gonna get by ID so it's gonna be again HTTP get public I action result okay let's stop this don't need it running I'm gonna put get by ID actually you can just make it like this and we're gonna be returning okay drivers Dot first or default and we're gonna be finding it based on the ID perfect let's download this again now we have drivers drivers cut by ID so now let's try it out now put id1 and here I should see sir Lewis and if I go down I'll be able to see that I got sir Lewis and if I put id2 I should get George ID3 I should get Sebastian okay so now that I have the second endpoint working so first it's got all the second one is gonna be got by ID the third one I'm gonna be able to add drivers now so it's gonna be a post so now it does do this right now so inside let's stop this let's put this down and here what I'm gonna be doing just make sure this is in the right frame okay that's fine so here oops now we need to add the new actions it's going to be HTTP post and we're gonna add that out just gonna call it a driver public I action resolved uh driver and it's going to take a driver called driver very simple straight to the point return okay underscore drivers dot add and we're gonna add the driver very simple why is not happy let's see so because adding does not return anything so I'm just going to put this here and I'm gonna be returning and okay so now let's run this again dot not run now if I just need to flash this straight out driver try it out I'm gonna utilize the ID I'm gonna give it the ID number four uh let's see who we want to add uh let's put uh say uh let's put Sergio photos he should actually have a different story so let's put driver number I think it was uh I think it's 11 and it's a little bull okay now let's try this execute we got a 200 and now if I do it get all drivers right out execute I'm basically not able to see it here why oh I think I know why because I made a treat only it's made static so let's stop this and let's run this again and now let's go back to my web browser and let's add this and now let's execute this and here I can see that I have Sergio has been added into my database okay perfect so now that we have created the main three which is going to be the gut I got all get by ID and post we're going to see the delete and then patch and then once we have covered all of that we can actually now move into the next step which is actually creating our DB context so let's go back here and let's stop this let's put this down and basically here what I'm going to be doing is I'm gonna put http uh delete because we're going to be deleting and I'm going to put route delete driver and I'm gonna put public the action results delete the driver and all I'm gonna take is the ID of the driver and it's going to be very simple um so first of all we need to find the drivers so we can put foreign driver actually let's make a driver equal drivers Dot first or default and we're just gonna match it on the ID equal equal ID so if all of that is working as it should what I can need to do is I need to put underscore drivers okay so let's make a double check so if driver is not equal to null so actually if it is not we're just going to return not found and then we stop the request here and there return not found as if it actually there is a driver all we need to do is drivers dot remove and I'm gonna pass the driver here and then all I'm gonna be returning is no content and that's it so let's try this out so first we need to run it so let's go to terminal dot not run it's running let's go to our web browser and let's I'll search you again execute and then let's run this again we should be able to see four we have four of them now let's refresh this we can see that we have our daily drivers let's do this again to make sure that it's there try it out execute I can see the four drivers now I'm going to be removing Sergio so try it out ID number four execute we got a new content which is exactly what we want and now if I go here and select all drivers I'm able to see only three drivers perfect so that means that our delete is working as it should be so once that has been completed uh I think we have completed now three uh actually four out of our actions the last one is going to be patch and basically patch is going to allow us to update our records inside our rest API so let's go back to our Riders let's stop this let's make this smaller and here what we're going to be doing is we're just going to put HTTP patch and we're going to give it a route update driver public action results update driver I'm just gonna take a driver driver and we're gonna be doing the same thing as we have done previously we need to make sure that this driver exists so far driver equal underscore drivers DOT first or default matching it also on the ID okay let's change this name from exit to existed existed driver yeah it needs to be capital driver dot ID okay so similar f oops f driver actually exists the driver is equally equal to null we're going to be returning not found else we're gonna be updating it so we're gonna be let's say a driver actually existing driver dot name equal driver.name existing driver dot uh team equal driver.team and existing driver dot driver number equal driver dot driver number okay and then all We're not gonna be returning is no content okay so now let's run this [Applause] perfect now let's go to our web uh let's refresh this and here we can see that we have our patch let me get get all execute we got everything here so let's see this and this update um Sebastian so if we're gonna change for example Sebastian's team we're gonna be changing it from Aston Martin for example to let's say McLaren and let's execute this and we got a 204 and now if I execute this I should be able to see that Sebastian is now moved from Aston Martin to McLaren perfect so now that we have covered the five five actions that we needed which is got all got by ID post delete and Patch the next stop for us is we're going to be actually connecting to a database which is going to be a SQL light and once we connect to our database we're going to be creating our DB context we're gonna be actually adding uh adding migrations seeing those databases choosing the database uh that they're seeing the table inside the database and once we do all of that we're gonna be basically winding it up into our controller and then uh we're gonna be basically updating all of the actions so so that we can take benefit of that so in order for us to do this the first step is we need to install some packages okay so now let's go back to Rider and I'm gonna stop this and let's start installing our applications so sorry install all packages so the first thing that we need to install is dot nut add package Microsoft dot entity framework core dot SQL light perfect the next one is going to be.net add package Microsoft dot entity framework core dot tools perfect so now that has that has been done let's do that not built again and now if we go to our CS approach again so just so we can make sure that we're utilizing.net7 packages we can see here that all of our packages are basically refreshing the latest and greatest which is going to be that note 7 version 777 exactly except the swashbuckle which is still on the other older version but other than that all of the Microsoft nuget packages are following the.net7 versions which is great so once we have done all of that the next step for us is to start actually creating our DB context so so inside our application we're going to be creating a new directory and we're going to be calling it data and inside the data we're going to be creating a new class and we're going to call it API DB context and here is going to be very simple so the first thing you want to do is we want inherit from the DB context class and then once we have done all of that the next step is we need to actually create a Constructor so it's going to be sea tour and here I need to pass the configuration so I'm going to put DB context options and I'm gonna pass API DB context and then here I'm going to make it as options and then I'm gonna pass this to the base class options simple as that and now once I have done all of that now I need to create my table and the way I do it is going to be public DB set it's gonna be called driver so because we want a table called driver I'm gonna call this drivers I'm just going to make it get unset so let's put this here perfect and now if I do not build everything should be building correctly will succeeded great so the next step is I want to actually create my connection string so here I'm just gonna add connection strings and I'm just gonna call this default connection and it's going to be a very simple one so we're gonna put the data store data source equal just going to call it F1 dot DB and we're gonna put as the cash equal shared that should be fine so now that we have added our API DB contacts either the connection string the next step for us is we actually need to update our program.cs so we can inject our DB context into the the eye container of our application and once it is there we can actually utilize this so let us go to our program.cs and inside our program.cs what we're going to be doing here is let's inject this so in order for us to inject it is before we actually do the app builder we're gonna do it here let's say online number 10 and we're gonna put Builder dot Services dot add DB context and we're gonna be passing the API oops API TV contacts that we had exactly and then once we have done all of that we need to pass the options uh let's put this in the new line oops I'm going to put options dot use sqlite and then from here all we need to do is just make it utilize the connection string that we have so it's going to put Builder Builder dot configuration Dot getconnectionstring and we're just gonna pass the connection string name which was I think default dot connect default connection let's copy this and program.cs and let's put this here save and now once we have done all of that let's do another.net build perfect now I will uh application is building successfully so right now what we have is we have created our API DB context with our table we have wired it up into our application we added the connection string the next step for us is we need to create a migration script because currently what we have here is we have a database implementation of our application but we don't we don't have a database and the way we're going to be utilizing that is we're going to be utilizing the EF tool that's going to allow us to actually translate our requirements from our application DB contacts into the actual database itself so first of all we're going to be seeing how we can actually install the CF tools it's very simple and then once we installed it we're going to be seeing how we can utilize the migration in order for us to create the skeleton of our basically the ddl files of our application and then we're going to be seeing how we can actually create our our sorry to create the ddl for our database and then we can see how we can actually create our database utilizing the migration tool or basically The Entity framework tool so let's go to our browser and let's look for EF enter Entity Framework tool let's put terminal and let's see how we can install it so let's make see if this is clear yep so we can see here in order for us to install the tool all we need to do is just put this inside our terminal so because I'm on Mac I can put it inside my terminal if you are in Linux what you can do is you sorry if you're a Windows or Windows you can put inside your Powershell inside your windows terminal and it will be able to work as well so let's open my terminal and because I have already installed an older version uh let's see what's going to happen if you already have an older version it's going to tell you that's already installed you need to update but let's do it dot not tool install global .net EF and we can say it's already installed for me because I have already a previous version but for you if you don't have a previous version it will install there now if you already have a previous version you want to update it's very simple we're gonna put dotnet tool update dash dash global.net dash EF and now it's going to update my tool and we can see here that my tool has been updated successfully from the latest version which was 6.9 which was supporting 4.6 to the version 7 which is the latest version that we are currently on and that's exactly the one that what we have needed here is to actually utilize all of this in order for us to basically utilize the the power of the Entity framework until the uh utilize the power of Entity framework core 7 in order for us to be actually utilized inside our application so it says here as well that we need to add this package.microsoft.design into our application so let's add this package so let's copy this let's go to Rider and let's add it and now that we have installed all of that now if we go back to our so I suppose we can see it has been installed successfully the design and now let's start with creating a migration so the entire concept behind behind creating a migration is as follow so we have our class we have our application DB contests but we don't have the actual SQL file that's going to be responsible for creating our application and because we don't have the actual SQL file we're gonna be relying on Entity framework and only for for it to actually create the translation with whatever we have inside our c-sharp classes into an actual SQL file and that's what the migration means it means migrating from SQL from c-sharp to SQL and that's going to be fully done by Entity framework core we don't have to write it manually everything that we managed for us so let's do this right now so we're going to put.net and because it's sort of not uh it's a part of our.net framework we're gonna put the F because we're going to be referencing The Entity framework cool tool and then we're gonna put add actually we're going to put migrations because we're going to be adding a new migrations and we're gonna make sure that we're gonna be adding it so that's not referring that's not the framework uh yeah for referring to the we're going to be utilizing the Entity framework tool then we're giving it that command uh actually we're going to give it what type what do we want to do with Entity framework so we're going to say that we're going to be utilizing the migrations and then we're giving it what is the action within the migration ad and then when you need to give it a name and I'm going to put initial migration foreign and I should be able to see a new folder popping up here which is called migrations sometimes oh it's appeared and here we can see that I have a new migration file has been created and we can see here that I have a representation of my database within SQL we say the ID is an integer it's basically the primary key it has Auto increment I have the name which is tax I have a driver with driver number with an integer and the theme is a text and we have seen that it has attached a primary key to my table perfect so now that I have to get the migration the next step is basically I need to actually execute this migration so it's always in two steps first we prepare it we see the script that has been created to make sure everything is as it should be and then once we actually see that this is the exact case that we want or basically this is what we want we can actually implement this into our database and the good thing for us is we don't have to specify a connection string we don't really have to specify uh to which database because the EF tool will be able to go to our application check whatever conduction string that we have and it's gonna do this migration for us so let's do this right now dot not EF database update and now if you take a look here before I run this we can you can see that I don't have a sqlite database for me but once I execute this it says completed and now if I come here I should be able to see my f1.db has automatically been created for me and if I open this yes let's connect with this let's download the missing drivers the status connection perfect now if I open this cut it and if I open my database here let's refresh this if we open the tables we can see here that I have my drivers table and if I open my drivers table I see the column that I have my ID name driver number and theme so what happened here so basically the once I run the database update command what it did is actually it went through the migration folder it checked all of the migration that exists there then it's like do I have this database yes if I do have it it will create it if not if if it does not have that database it will create it if it does have it it will skip the step then it will check what type of migrations that I need to implement into this database do I have all of the that start comparing the migration so it checks how many migration exists in the folder and it checks how many migration exists inside my database and if they are equal nothing will happen if there's for example one inside the migration folder that exists and it does not exist inside my database it will Implement that migration file into my database and it's the opposite if I remove a migration file from my database it will actually refer those changes but be careful when it reverts it might be data loss there so be careful whenever you're trying to revert any migration so that's basically the assessment happens to an individual framework when we're doing the anti-frame core tools so now what we're what we're going to be doing is we're going to go back to our driver's controller and inside this driver's controller right now what we're going to be doing is we're going to be updating it in order for us to actually utilize our ADB context and once we actually Implement our DB context here we're going to be seeing how we can actually save all of this information to our database rather to our in-memory database so first things first uh let's go up here and what I'm going to be doing here is basically I'm going to be removing all of this because we don't really need this anymore and basically what I'm going to be doing is okay so let's start adding our DB contacts we're going to put private read on the API DB contacts underscore context and then we need to create our Constructor and I'm gonna pass the API DB context here so it will utilize dependency instruction in order for it to cut all of the DB context options that it needs I'm just going to make it context and then once I have done all of that I'm gonna put contacts the equal context and then once I have done all of this now what I can do is just basically refer to my API DB contacts to go to my database cut all of the information that I need and based on the ones I have done all of that it's gonna take it's gonna make it really easy for me uh to basically get any information to any from the database save information in my database and update it so let's update first our gut so here what we're going to be doing is instead of connecting to the drivers I'm gonna put contacts the drivers Dot to the list it's very simple actually let's make it to list async and let's make this as an await and let's convert this into an async method racing and let's put here task and let's put this here and let's save this so basically here what we're doing is we are basically connecting to our ADB contacts we're telling it that you need to go to the drivers table once you get to the driver's table got me that got me everything that you have there put them on the list so that's what we have done here so the next step for us is we're going to be getting by ID so let's do this in a different line so just to make it easier for us to see what's the difference we're gonna put VAR driver which is the driver that we want to get and basically what I want to do here is I'm gonna put again connect to the let's make it await uh because it's going to be an async request we're gonna go to context and then I'm gonna put the drivers I'm just I'm gonna put first or default again based on the ID so same condition as I had before ID oops ID and here let's see so uh this is still not happy let's make this as an asynchronous uh action okay so let's see what happened so first of all uh I connected to my DB context I connected to my driver's table and then what I did here is I told them to get the first or default async whenever you match the ID to that idea that I'm passing and we can do this after this I can say if driver equal equal null I'm gonna return not found and then based on that once that is done all I'm gonna be doing here is I'm gonna put driver I'm gonna return driver with an okay perfect so now this is my second action has been updated so uh two two is down three more to go so now I want to update my post again it's very simple so all I need to do is I want to actually refer to my DB context so I'm gonna put context again what do I want to do it's going to be driver and all I'm stud uh if I want to add stuff I want to add and I'm going to add the driver as is and then here what I'm going to be doing is I'm going to remove this and the way that I also want to do is I want to save those changes into my database so contacts to save changes async and let's make this awaitable and let's make this as are you saying guess what perfect perfect so the next step is it's going to be similar to the get drivers so let me copy paste this instead of me writing it all over again and let's make this as an async as well async Tusk and here if I do this perfect so now how do I delete from my database very simple the way I do it is I connect to my database contacts drivers dot remove and here I just passed the driver and then I need to save those changes so I wait underscore contacts to save changes async and I can remove this perfect next and this is going to be the last one which is updating the driver again it's going to be the same logic so let me get this oops oops oops I'm gonna call this exist driver and let's make this again as an async dusk and here what we have done is basically a context again connect to the drivers first or default we need to update this so it will utilize whatever is inside that object driver ID and then once I have done all of that I'm able to update it and the way that I just save those changes I just await underscore contacts dot save changes async and that's it and now basically if I do not build we can see that the build is succeeded and if I do not run it is running so let me go to my back to my web browser and let me go to my Swagger file and Let me refresh and here I can see that I have my five actions it's not because I'm utilizing the database the database right now has my uh the database has my table but it's empty so now if I do get all or get by ID it will not be able to find anything but once I start adding I will be able to utilize these actions so let's try the drivers first just should be empty now execute it's empty cut driver by ID should give me not found we got another not found perfect and now let's see trying a driver so ID equal one name is Lewis Hamilton driver number is four four and team Mercedes AMG F1 execute we can see I got the 200 and now if I click on execute on the get all drivers I'm actually able to get all of my drivers basically a driver that I've just added and now let me go to Rider again and let me open my database and if I click here and I can see the sea view data yeah added data I'm able to see inside my database that I have Lewis information already added directly there perfect now let me add another driver uh let's say let's first let's add another driver so just to make sure that we have multiple drivers so the second one is going to be George Russell 63. same team and now if I put get all I'm able to see both of them and inside here if I do refresh I should be able to see the two drivers available inside my database perfect now if I come here and put cat driver by ID so before it was 404 now if I click on it I'm able to see a 200 I'm able to see those if I put driver id22 I'm able to see George's information perfect so now that we have made sure that our gut oil is working get by ID is working and post let's try the delete driver so let's say I want to delete the charge so put two execute we got a 204 and now if I come to my database refresh I should should not be there anymore and if I come here I put select all we should be only seeing Lewis perfect and lastly if I want to update the drivers so it's going to ask me the driver number is going to be one name Lewis Hamilton driver Lumber is 44 and that team is going to be we'll say this AMG F1 Petronas and execute I got a 204 and now if I click on get all drivers I should be able to see the team updated from Mercedes AMG a phone to am Mercedes AMG iPhone petronos perfect and now if I look inside my database and I refresh this I'm able to see that the team name has been updated to Mercedes AMG F1 Patronus perfect so right now what we have done inside this uh so far inside this video is basically we created an uhnet7 web API we utilize an in-memory database we created Five actions got all got by ID post patch and delete and we were able to see how that works then we have added our tables sorry we have added our uh DB context and then we have wired it up inside our application to make sure to work as it should be and then when then we have updated our controller so they will take full advantage of our DB context and make sure are working as they should and then once we have done all of that we have tested it out make sure that everything is running so and as well we have installed the Entity framework tool we were able to understand how the migration work database update works so on so forth so this is the full overview but now we're going to take this a step further and we're going to be seeing how we can actually implement unit of work which is a way where we can actually communicate with the database without actually referring to the DB context directly so what we're going to be doing here is we're going to be creating a service based uh approach which is the unit of work Tower database and once we actually create the service space to our database what we're going to be doing is it's going to allow us to actually inject our service inside our controller and then refer to work it from there so basically we put all of the logic that we want to manage our database in a separate place and all we need to do is just refer to it to what we need and basically call those actions from there so let's get started so what is a repository pattern the repository pattern and unit of work is basically an abstraction where we are able finally to decouple our apis or basically our web application from our data layer so we're able to do separation of concern where basically any changes to the data it will be within the data layer and basically our application will be able to consume it rather than having those two embedded together that's why it's a much better approach for us to actually separate them and have them completely separate so the unit of work and the repository pattern who will basically allow us to have these decoupling between our application our between and our data layer and one of the main benefits of this is basically for example it will allow us to have a much more better Applause when it comes to tdd development test driven design because in that way we can actually mock all of our database stuff without actually having to rewrite anything within our logic class and our web apis because all of those can be actually switched over with the within for example a mock database and that way we can actually have a much much better stability of our application as well it will make all of the layers Loosely coupled with independency interactions so we don't really have to be hard coding them inside our application so for example if I want to change my database from postgres to sqlite I can easily just switch it open in the data layer the application will not be effective if I want to switch it to SQL Server my SQL to a non-sql DB my application will not even know that's changed the data layer will be taking full charge of that without actually affecting my application like in any single way so that here we can see that this decoupling between the data layer and our application it's a really really powerful thing and this is something that really we need to actually Implement within our application in order to in order for us to have that flexibility and basically this flexibility will allow us to have better testability of our code and much more stable application so first things first is inside our formula API let's create a new folder so I'm going to put add directory and I'm going to call this core and inside my core directory I'm going to be creating a new interface and this interface I'm gonna be giving it a name I generic Repository perfect let me close this for now my database and what I'm going to be doing here I'm going to make it generic and then the reason that I made it generic is because let's say in my database I have 100 table 15 tables 20 table no matter what the number is I don't wanna excuse me I don't want to recreate all of the interfaces specifically for the default patterns for all of them so what I can do is I can create a generic one and then basically what I can do as I can Implement those inside the tables one so let's say I have three tables I can just refer to the generic one and basically do the implementation from there so right now I'm gonna be also doing here I'm gonna be adding all of my default actions that we usually do against database so it's going to be tasks I in the numerable of T and this is gonna be forget all perhaps make it call it all and then I'm gonna put task of t for example here is gonna get my ID so you can see here that we are referring to all of the default crud action that we actually wanna we might wanna do against a single uh entity and that's why it is a generic one because whatever the table is or whatever the entity is we're gonna basically even get all got by ID add update and delete so these are gonna be basically whatever the table is inside our database there is a big chance that we're going to be utilizing these five actions against it so it's good to make it as a generic repository in order for us to directly utilize it instead of rewriting it every single time so once we have done that then we can put tasks as Boolean and we're just gonna put add and we're gonna pass t as an object and then we're gonna put task bull ah this is gonna be update and we're gonna put T again entity and blastly we're gonna put task bull delete T dot entity not DOT entity perfect so once we have created all of that the next step is inside our code we're going to be creating another interface and this artiface is going to be referring to our driver interface so I'm going to put idriver Repository I'm gonna put I actually that's not here so now that I have my iDrive repository I can just refer to the I generic Repository and make sure that this for a driver so and this is not a class it's an interface okay so what did I do here so right now if I create driver uh drive a table if I have a teams table if I have a FIA table if I have any table that I want inside my application let's say I want the equipments the cars the Personnel all of that so all of those tables were gonna have the same actions add update delete got information gunpal ID all of that I don't want to recreate those things so that's why we can see here it had from through the generic one that I have created I was actually able to refer to that interface and basically I have passed the type of object to it so because I have made it as a generic of type T I was able to refer the driver here into the class so as you can see here I was able to make sure that it's for this generic type I was make I was passed a driver so we can see here that SSD is a driver so the generic object that was the now it's being deferred to as a driver and now I'll be able to utilize this repository with all of the actions that exist within the genetic repo so I hope that makes sense so now uh basically uh when for anything within the iDrive repository all of those actions is going to be basically belonging to the driver table so once I have done all of that the next step for me here is inside here I'm going to be getting a new interface again and I'm gonna call this I unit of work perfect so here what I'm going to be doing I'm going to refer to my interface and I'm going to put I drive a repository I'm gonna call it drivers get and I'm gonna of course make the task which is gonna be the complete async which is basically going to refer to save changes perfect so now that I have my unit of work ready and the reason that I want to have my unit of work ready here is basically what I need what I want to do is I want a way so the reason so let's take this step further so what is unit of work the unit of work is a way where we can actually abstract all of the logic of my databases and the way that I'm doing that right here is for every single table I'm creating a set of instructions that I wanted of our actions that I want to be able to execute against this table and I want basically a way where I can put all of these instructions at for all of for every single one of them and the best way to do it because we're going to be utilizing as what the I the dependence injection is to have the interfaces and then have the implementation and basically what I can do is because if I'm gonna have a lot of interfaces a lot of implementation and either way where I can actually map those two together and here the unit of work allows me to actually do those mappings so the way that I do it first I have create created right now the eye unit of work interface then what I do the implementation for the unit of work I can do the mapping there and I will be able to actually be able to utilize this and we're going to be seeing this but in action but I just wanted to explain why do we need it and why are we doing it this way so inside my core folder now I'm just going to be creating a new directory or a new folder and I'm gonna call this repositories repository is okay so inside this Representatives I'm going to be getting a class and this is going to refer to the generic repositories that I created previously and the way that I'm going to be doing that is I'm going to make sure that again it's generic so it's 5T and then I'm gonna inherit the I generic repository again it's going to be of type T and I'm gonna make sure here that where T is Plus and then it's going to say okay you're gonna you're implementing the I genetic repository but you are missing all of those numbers so let us Implement those numbers automatically so let's make click here it's going to tell me Implement missing numbers I want to implement them all and we can see here that all of my members has been added now we're going to implement them all but for now we need to do some uh work before we can actually Implement them so first thing that I want to do is I want to refer to my application DB contacts because at the end of the day my API my application DB context is going to be what doing the communication with my database so we're gonna put protected API DB context I'm going to call it context and then I'm gonna put internal excuse me DB set of type T because here we're gonna specify to which table we want to connect to I'm going to call it dbsat and then once I have that all I need I can put a locker so I'm gonna put uh in turn also make it protected protected yeah and it's gonna be a lead only I logger of type actually without this we're just gonna call it underscore Locker and I want to make this without the underscore okay so now that I have my contacts which refer to my DB contacts I have my DB set which refer to the table and the logger so these are the foundations that every repository will need it's gonna basically need to which DB contact is going to be connecting to so that's the first part then it's gonna know to which database is kind of actually executing this information and the logger is there so we can catch anything anything that might go wrong or just to have more information available so once that is done I need to create a Constructor and this Constructor is going to inject all of these three so again we're gonna put API DB context it's kind of equal to context actually just make this like underscore contacts nicer and let's make this underscore DB set so it's nicer and then the next one is going to be the logger and here it's gonna be oops logger actually it's going to be an eye logger not logger okay and all I'm gonna put here is underscore context equal context and underscore logger equal logger and then I'm gonna be referring to this dot underscore dbsat equal context dot set and here I need to set the type of table or whatever it is so what I'm doing okay why is this green let's see okay that's fine so what I'm doing here is basically I'm initiating the DB context and the logger through dependency injection it's going to take out all of them from the startup class but this is really interesting so here what I'm doing is I'm telling it that this DB set or this table what you're going to be doing is you're going to connect to the contacts that we currently have and because you have connected to the contacts that we currently have you need to do is you need to set it to type D or to whatever T it is and then once you set it to type t you are able to actually utilize it and that's the way we are currently using it let's see okay that's fine so once we have done all of that the next step is we need to start actually implementing all of our actions so again any questions on this please feel free to put them in documents down below so once we have done all of that now let's start implementing our uh all so yeah what we can do is we can just make sure we can say return they reset dot to list let's make this as an async and let's make this tutorial and let's make this available so basically oil is going to connect to the DP set and get all of the list async now let's Implement get by ID so the first thing I want to make this async and then I discovered something here that this is now this is not does not have an ID so I'm gonna pass an ID here and I'm gonna go to I generic repository and update the ID here as well and then let's go back here and here for example I need to remove this and then I'm gonna put return I wait DB stat dot find async I'm gonna pass the ID and here this could be nullable so it will be good to actually the turn is not right let's see TST entity or null so let's make this as nullable let's come back here and let's update this to nullable perfect now let's do the add again the ad is going to be quite simple so let's make this as a sync I can and all I'm going to be doing here is put a weight underscore DB set dot add entity oh we cannot await this and we need to make it they think yeah all I'm doing is return true perfect now for the update I'm not going to implement the update in a general in a generic way well I can let's see so I'm gonna put a weight uh DB set async dbsat Dot update I'm just gonna pass the entity uh let's see here this there's no update I think it's there execute update async no just update without this so let's remove that weight and I'm gonna return through and as for the delete it's gonna be similar case I'm gonna put dbsat dot delete or dot remove actually entity is there remove async let me let me double check nope and I'm gonna return through and let's make this a weight async okay perfect so now that I have these available for me I have my generic DB context available I have implemented my default repositories that I have so what did I do here I created my generic uh repository I have inherited or implemented the interface that I needed to do which is going to be the I generic interface I generic repository interface I have implemented that I know that I have a default implementation so what I'm going to be doing right now I'm going to be creating a driver implementation for this and then once I create a driver implementation of this utilizing the igenetic repository and the generic repository which you're going to see how we can actually do that it will be much more easier for me to actually just after that to just refer to all of the DB actions inside my repositories written rather than having everything be hard-coded into my application or basic into inside my controller and the reason that I do that is of ease of abstraction so that what does that mean so in case that for example down the road I want to switch up my DB contacts from utilizing postgres to uh solitos and SQL light to postgres it's all I need to do is update my repositories one thing in place all of the data is there instead of actually trying to implement or do the update inside the controllers services so on and so forth so here we can see the power of our Repository so now what I'm going to be doing here is uh let us create a new file and this file I'm gonna call the driver Repository perfect and this driver repository is going to inherit the generic repository it's going to be driver and it's also going to implement the IE driver Repository okay now let's fix those references perfect that's kind of time you have not implemented thank you very much as implementing the missing number so here we can see that it has automatically injected everything that we need inside our Constructor so that's something that it took care for us directly the next step is what I want to do here is I just want to see how we can actually override some of those actions that has been available for us and we're going to be seeing how we can actually create new uh functionalities for our database and basically say I want something other than the crowd so for example let's say I want to get a driver by the driver number instead of an ID so we're going to see how we can actually add that Implement that as well as we can see how we can override a certain action which has been implemented already and then we're going to be Implement updating our controller to take advantage of this so let's say I wanna override my old function so how can I do that very easier I need to do public override async because basically we are here we have inheritance so we can override and I'm gonna put the all actually we need to specify the tasks which is I innumerable driver in this case that's going to be the all and for example why is this not suitable what did I call it generic yeah that's all let's double check okay let's finish this and then we'll do it so I can do for example try catch if I want here and what I can do here is I can add extra conditions for example to all so what I can do is I can put return underscore contacts dot drivers oops the drivers dot where I can add a condition for example where x dot let's say ID is less than 100 I don't know some condition like that and here for example I'm able to utilize this but why is not allowing me to override so let's put first put this as to list async uh uh so wait this I think I know the reason so the main reason here is I need to mark this as virtual so I'm able to override them apologies for that so virtual virtual virtual and virtual is still not uh it's just turns 6 a.m so I apologies for that and let's do virtual and now if I go back to my driver repository I'm able to override it and basically add any condition that I want and now let's see uh get a driver based on the driver number so if I want to add this new one I don't want to add it to the generic one because I don't want every single implementation to have that function all I wanted to do is for the driver itself so what I do is I go to the interface for that driver I'll add the extra functionality that I want there and it will be automatically forced on me to implement this inside my driver repository so let's add this here let's make it a task of a driver and I want to make it nullable and I'm going to say get by driver number can buy driver number and we're gonna pass here driver number and now if you take a look directly and into my driver we can see there's quickly line because it's telling me there's one method has not been implemented so right now if I come here I can see that it's forcing me to implement it and I make it async because I have not implemented inside a generic one I don't have to override it I can just implement it if I have implemented inside my generic I need to do an override so now what I can do is simply I just remove this and all I'm gonna put is try and here I'm gonna put a let's say got so I'm gonna be returning context Drive driver DOT first or default async and I'm just gonna be matching by driver number equal equal driver number and that's it oh I need to make an await here okay perfect and now let's do a build although it's not finished I just make sure that everything is still working as it should be and we can see the build has been completed perfect succeeded and now next what I need to do is I need to implement the same so if we take a look here I put the i unit of work interface so I need to implement this I unit of work and then all what's left is just to wire it up inside my program.ts and then I can take full advantage of it inside my controller so let's see how we can Implement that so inside my repositories here or inside my data folder for example I can just create add new class I'm just going to call it unit of work and once it has been created the unit of Works fairly simple all I need to do is I unit of work basically referring to my interface of unit of work and it's good to have the eye disposable available so we can actually clear up the uh it's put for it's better for garbage collection so let's put this here let's do the implementation okay let's Implement them perfect so we can see here it already started implementing everything for us which is great so the next step here first of all let us assign the DB contact so it's going to be a private should you just make it public actually private sputter private API read on the API DB context I'm just gonna call it context oops context and then I'm gonna add the logger private read on the I logger without this underscore Locker I'm gonna add here I'm gonna update this to have a private set and then lastly what I want to do is I want to create a Constructor and inside my Constructor I want to pass this so I'm gonna put the API context context as well as the I logger logger and then once all of that is done first of all I want to put the underscore context equal context and then underscore logger equal logger and then what I can do I can just implement the drivers equally new driver Repository and then all I need to pass here is the context as well as the logger and that's it so what I have done here is I have wired up my API DB contacts and my logger to my repository and I was able to do this connection between the interfaces that I have as well as the implementation itself and all I have to do left here is to implement these two so the complete async I need to make this as an async and let me remove this and this is going to be a weight underscore contacts.savechanger.async very simple and lastly within the dispose I want to dispose of the DB contacts properly so I'm just going to put this pose and that's it so here what I have done is basically I have created my uh I have created my implementation of the unit of work what I have actually able to link the implement the interfaces of my implementation as well as the actual repository itself so I created the interface I create the implementation I was able to link them both together inside this unit of work so the last step here is another I need to wire this up inside my program.ts and then I can update my program my controllers so inside my program.cs if I go all the way down after this all I'm gonna be doing is just adding this implementation so it's going to be a very simple builder.services .adscoped it's going to be i unit of work and then we're going to put unit of work it's very simple as simple as that and now if we go back to my controller drivers controller instead of injecting my DB context here I can just update this to be a unit of work and I'm gonna call it underscore unit of work and remove the DB contacts is going to be unit of work and then unit of work and let's do the mappings here perfect so now here we can see first of all I was able to completely remove the dependency from the hard-coded dependency of my application DB contacts I'm utilizing my unit of Forex service in order for me to refer to my le database action that I need to do so now all I need to do is just update my actions here so first of all a discount method we're gonna change this into unit of work the drivers and instead of all lists it's going to be to all so that's it I'm just calling now the methods get by ID instead of doing direct connection like this and putting the condition here is going to be unit of work dot drivers Dot getbyid and I'm going to pass the ID very simple instead of directly adding it like this and saving changes all I can do is I can put oops all I can put here is underscore unit of work the drivers dot add driver let's make this a wait and here I'm gonna put a weight is a underscore unit of work dot complete async that's it deleting a driver is going to be way more easier so again instead of having all of this here unit of work the drivers oops don't get my ID and ID for example and here instead of deleting it like this all I need to do is under await underscore unit of work dot drivers Dot delete I'm gonna pass the ID actually I need to pass well I forgot what I did I need to pass the driver itself and then awaits underscore unit of work dot complete async and lastly let's update this one here so instead of directly again Corning it I can put unit of work dot drivers dot get by ID I'm gonna pass the driver.id and updating it like this is gonna be equal to uh await underscore unit of work to the drivers dot update existing Drive driver actually and then all I need to do after that is await unit of work to the drivers sorry don't complete async and that's it so here we can see that although the number of changes that we have done is instead of actually referring to my API to API DB contacts directly I was able to refer to the unit of work and although it might not seem as a big change or why do I need to do this but trust me whenever you want to change the database type you want to do optically you want to add the new any new uh structure to your database you don't really need to rewire up all of those conditions inside your controller so you can see here like let's say I want to add certain condition when it comes to getting the driver instead of going to every single controller where I have got my ID I'm doing that I can just update that in a single place and wherever I'm having the gut by ID function it will be automatically implemented and this is a very minor benefit compared to all of the other benefits that we might get with the unit of work implementation so let's run this now okay it's telling me I have an issue let's see what is it so now there's a problem with the logger and it's correct I have not injected it inside my program.cs so away we can actually fix this is by try to removing it from here and here instead of referring to the eye logger what I can do is I can refer to the I logger Factory I'm gonna call it oops I logger Factory I'm gonna call it logger Factory and basically here what I can do I can just create a file it's called logger I can put logger Factory see if this is looking right yep dot create Ops dot create logger and I can just give it a name I'm gonna call it logs and here instead of referring to logger I can prefer underscore logger but now this should work now let's run this again perfectly it's running now let's try this out so let's get all drivers now we got an error because there's an issue while activating unit of work let's see what this issue is so it says unable to activate unit of work that's fine let's go back to our controllers it should be our unit of work see a typo can cause that so let's try this again and let's go back here and let's execute this and now I'm able to get my information exactly the way I wanted to let's get my ID let's put idea number one execute I'm able to get Lewis information perfect add driver let's add George again execute this we got a 200 and now if I get get all by ID I'm getting all of the information perfect delete let's delete the George execute 204 and now if I got got all drivers I should only be able to see Lewis perfect and updating let's say I want to Patronus one for example and execute now if I go all the way up we can see here is still Patronus but if I get execute again okay this needs to be taking a look at oh okay what is it okay we got an error same idea is already being okay so this is something that we need to make sure that we are following because it's already being tracked and what that mean is whenever we are getting any number from whenever we're doing any query with an Entity framework core Entity framework code by default it will keep track of that object in case it needs to be changed it's got updated so Entity framework it's very smart so let's say we are utilizing an object this object has been sent to the user and basically what Entity framework call is basically keep tabs on that object that's this object change that object have anything that got deleted updated so on and so forth but because we're here we're gonna we're utilizing an API and basically we're having this conducted mechanism with it what we can do is we can tell Entity framework like please do not drag this object that we're currently getting because we want to basically make sure that we are covering this so let's see how we can do that so inside my generic Repository so here for example what I'm gonna do is for every single one of this I'm gonna add Dot as sit here to be set dot has no tracking has no tracking and basically the has no tracking mean the attack Entity framework do not track this object just get me the results and I'm gonna get also do it here for the get by ID so here we can see that we have a bit of a dilemma we cannot implement the asphalt for tracker Forgot by ID so away we can actually resolve this is what we can do is we can go to the implementation of this we can override it so we can come here and we can just put similar to how we override the let's make this smaller the all what we can do is we can put public override async task a driver I get by ID as taking an enters an ID and the way we can do it just put try again and then here what I can do is we can put return await underscore context dot drivers oops the drivers Dot first or default async we can make that much here x dot ID equal equal ID dot as no tracking foreign and now this should be able to resolve our issue let's try this again let's run this and let's come here and let's try to update again and basically we got the top of four and now if I update this I'm able actually to get the 200 with Patronus one perfect so this is basically is how we can actually implement the unit of work uh the unit of work within our web API and let's do a quick overview of what we have our accomplished so far so once we have created our web API once we are able to wire it up to our DB contacts so first thing that we did is we have created our repository folders where we have created a generic repository interface where we have specified all of the default commands that we want to implement there so that's the first thing second is we have created AI unit of work interface where we are actually telling the uh we are mapping all of the different interfaces for our unit of work so that's the second thing then we have implemented a default implementation within the repository for all of the interface default interface generic interfaces that we have so we created the implementation for all get by ID add delete and update once we have done those uh Delete and update implementation then we Advocate it's much more specialized implementation for that drivers and basically from there we were able to override certain actions like the all get by ID we saw how we can actually add a custom command for our database which has got driver by driver number and we can see how easily we can get it and basically implemented and once we have done all of that we basically actually wrote our unit of work implementation where we were actually able to create an implementation for the interfaces and once that has been done we basically just wired it up into our program.cs and then we have updated our controller in order for us to basically utilize every single aspect of this every single aspect of the unit of work rather than calling directly the DB context and that's it basically and here we can see that the power of unit of work that it provides and basically how much more flexible our API is gonna get because we are utilizing this so I hope this video was helpful if you like this video please like share and subscribe it will really helped the channel if you like access to the source code please consider supporting me on patreon or buying me a coffee and thank you very much uh for watching this video and have a great day
Info
Channel: Mohamad Lawand
Views: 24,587
Rating: undefined out of 5
Keywords: .net, api, beginner guide, step by step, csharp, c#, dotnet, dependency injection, code with me, coding, ef core, sqlite, database normalization, database, entity framework c#, entity framework core, entity framework, asp.net core tutorial, rest api, crud, repository pattern, unit of work, uow
Id: nIOqO5N2_ss
Channel Id: undefined
Length: 96min 26sec (5786 seconds)
Published: Thu Nov 17 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.