Using EF Core in Blazor Server the right way

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody and welcome back to the code wrinkles channel for a brand new video and guys this time it gets really really serious because we're gonna talk about a topic that is very very important and this is how do we really use entity framework core in blazer server applications now of course we won't use entity framework core in blazer webassembly because blazer webassembly actually runs client side so we can't really talk to a database there so we need an api but in blizzard server since everything is rendered on the server we can of course use entity framework directly into our components and this is a reason why i think that in most of the cases going for the server side blazer might be a very good approach when you start to develop a brand new application because you don't need to really develop or write an entire api layer only to get some data you can get it directly from the database but before we get really coding for this video we will also spend a little but a little bit of time talking about why this is very very important and of course we all say blazer is cool it's it's really nice it's it's really cool to have it and we are happy as developers to be able to have uh or to be able to offer this type of experiences to our customers and to our end users and this is everything fine but blazer is an entire different programming model and yes it's true it is built on top of asp.net core but the way that we actually have to think about our applications is a little bit different and we will see especially when we talk about server side blazer or blazer server we need to think differently than what we are able to think about when we write regular asp.net or applications and the reason why we need to think differently first of all is that we actually don't work with the http context anymore or better said we don't really handle http requests because if you imagine what happens when a request for your application comes in so the really first time that the request comes in it's a regular http request and it goes through the entire middleware pipeline and things like that and then it actually serves the application itself but once the application is served every time that the user clicks a button or does something in that application there is no http call anymore everything happens through a signalr connection so through websockets communication so let's say you click a button this means that this information actually is sent to the server via that websocket connection then the differential html is calculated and sent back to the client via the exact same websocket connection so everything you do in that application actually does not use http at all and the reason why this is a little bit problematic or the reason why we need to think our apps differently because of this is that the lifetime of our services is actually totally different and this means that for instance when you register services in regular asp.net core application in one way or the other they are scoped or their scope is related in one way or the other to the http request that is coming in and especially when we think about the entity framework core and the way that we use it this is very very important because when we add the db context to our asp.net application we do this as a scoped service which means that we will get a new instance of that specific service or of the db context for each http request that we actually receive in the application and of course if we receive several http requests then of course we will get several instances of the db context and each one can write to the database which is okay but what happens when we actually don't have these http requests anymore like we are in the situation in a blazer server application well the problem there is is that when you add the db context for instance this standard or classic way about using adb context like this method adb context because this adds the db context as a scoped service however since we don't have this idea of this incoming request anymore when we say scoped in blazer server we actually think about that it is scoped to the entire circuit now circuit is let's say the entire context that is established once the user gets the application for the first time and until it closes the browser or until the user does a refresh for that page and everything that happens on that page is a actually part of that specific circuit and the problem is that when we add a db context as code like we have it for instance here it means that we actually that we have only one instance per circuit and if we render on the screen at the same time different components for instance that needs that need to work with the db context they will actually work with the same instance of the db context and since the db context is not tread safe this will create a lot of problems for us and believe me when i say that i witnessed this firsthand uh this spring and start of the summer when i developed a real blazer server social media application for a university and i really encountered this problem and that was the point when i realized aha with blazer servers the server we actually have to take to think totally different when we worked with the db context and in order to showcase what is actually or what would be the best way to work with the db context in a beta server application i have used the blazer server template but i actually have added some a very very basic crowd components to it so that we can actually start working directly and not spending time on writing the component and before we go there we have the same fetch data which still retrieves this list of weather forecasts so this is not coming from a database right now and i have added a few buttons here for instance to create an entry if you want to create an entry to edit an entry if we want to update an entry or to delete an entry when we want to do that and what we want to do in this video is actually implementing these components of course talking to a database and i already have created the database for this with a weather forecast table so we will work with the same weather forecast class the only difference is that we actually uh let me go here and just show you uh so for the weather forecast class i just added here the uh id in order for it to really work uh with the database or with the entity framework as an entity and that's actually it so let's see right now how do we want to work and how do we really implement or how do we work with entity framework core and db context in our blazer server app and of course we still need the services sdb context because i would say because of two reasons first of all because for instance each time that the request comes in uh maybe uh well you want to inspect that request you register some middleware and maybe you want to you want to write data to the database and things like that so you can really do that and use it and of course uh what also earlier uh my um let's say obvious approach was that okay i use the db context also in the components uh where i need it for instance if we go here in this fetch data component right now if i want to replace this type of service that we have right now this standard that comes with this template i would simply go ahead and inject an instance of db context and use it there but then i will get the problem that i talked about earlier because then in this component i would use an instance of the db context but if i uh have another component in the at the same time that needs to work with the db context i would get the exact same instance so that would be a real real big problem and of course for for handling this type of things what we need to do is actually think a little bit differently and what does this actually mean so this actually means that when we think about how do we want to use db context is that we have to keep it as short-lived as possible and if you have experience with developing desktop applications it's exactly the same thing that you have to be careful about in in regular wpf apps because in that case once again you probably would use factories that would actually create an instance of the db context in the moment that you need it and dispose it right when you need it or right after you don't need it anymore and we need to think exactly the same way when we develop a blazer server application so what we would have to do is actually to create a factory for the db context that would be able to create us a new instance each time that we actually need it however the good news is that starting with entity framework core on.net five uh so entity framework core version five dot zero and upwards we have already a method that we can use and that would provide us with the db context factory instead we instead of it with the db context so let's go ahead and use this new factory that we have in ef core 5 and upwards in order to be able to create instantiate tb context instances and use them in our components to do that it's actually i said very very very easy we just have to use services and we have add db context factory and it's of course a generic method in which we will have to provide also the type of rdb context and that would be our weather debit context and then of course we can also provide here an adb context options builder instance to specify exactly the configuration that we want to use for our db context in our case it's a very very simple one because we just want to specify that we want to sql server and to provide of course the connection string to it and it would be exactly like we do when we register the regular db context like you see on the line below but in this case uh we'll use exactly the same thing on our db context factory use sql server and then we'll have to specify the connection string and that should be it okay so now we are we are done with what we need to do in startup.cs so we can move on and we can go to this fetch data component and this fetch data component uh of course we would inject this new db context factory here so we'd have inject i db context factory and we have to also provide the type of course and that would be a wetter what was it sweater db context and let's call it let's call it context factory and that should do it in order to be able to inject this you would also have to use this using microsoft hd framework because in this namespace we find this idb context factory interface and that would be it so now that we have injected our context factory we can go in the code below and here in this uninitialized async we can then replace what we have right now with getting or fetching some real data from the database so in this case what we would have to do is first of all to use this using construct and this is really really important because the db context as we know it is an unmanaged connection and putting it into this using would mean that once we once we get out of this using context we actually or the instance gets disposed so we don't have to take care of it anymore so in this case what we will put here is of course var city exit context equals that would be our context of factory and we have a method here that is called createdb context and this is actually what we need to call and that would create us a new db context instance with the options that we have provided when we have registered this con db context factory service and in that case what we need to do here is very very easy uh forecasts it would be a weight of course because it's we want to do this uh asynchronously context uh forecasts i guess and it's array because we have uh query async of course because forecasts is a weather forecast array and that should provide us with the necessary information so then we can delete this and theoretically right now we should we can run this application and check out if this really works and if this works of course what i would expect is that we will get an empty table because we really don't have any weather forecast data in the database so far we'll get into creating that that data afterwards and that browser opened on the other monitor so we bring it here let's go to fetch data it's loading of course because it's talking to the database and then we have this empty table so until now everything is fine because we got some data unfortunately the database was empty so we don't really have anything to display right here but we still have this create button so what we want to do of course right now is create a new weather forecast so i would say we we should go on into this create a forecast component and actually implement logic to create what we need here so first of all uh let's also uh using microsoft dot entity framework or because we want to inject uh the db context factory so let's have inject i db context context factory it would be of type letter db context context factory and uh that should be it so right now we also have a model here we have a form so we can take all the information that we have from that form and actually create a new weather forecast because it's also of type of weather forecast now of course in a real application i wouldn't uh i would have different models for the front-end part and what we want to write to the database but for simplicity sake right now we really use the exact same model because that this makes actually our job easier right now so what we will do is exactly what we have done also previously and this insert forecast method will create a new instance of the db context so we'll use the context factory context factory and here we should have create db context and that would create a db context for us now of course right now i don't have any model validation because i said the main scope or the main target of this video is to see exactly how do we really work with anti-framework core and bezel server the right way not how to do model binding validation and things like that for this we have other videos on this channel so here what we can do here is without any other validation or things like that we can simply say here context of forecasts dot add and what we want to do is we'll add our current forecast and uh that should do it and of course we would need to await and here uh context dot save changes async and that would save our changes and that should actually do it right now okay once we okay theoretically we would also uh have to clear the data but you know what we can do here we can use navigation manager oh let's let's make it let let's do that and navigate back to the list after we create this so inject navigation uh navigation manager navigation that should be it and after we are done with this uh navigation dot navigate to and here we want to navigate to fetch data okay so let's try this out of course let's run this application again and it's still opened on the other screen but there's no problem with that i'll just bring it back here where it belongs so we go to patch data now we get the empty table we go on create entry uh here we have a date that we want to to input and uh yeah of course we we we can set probably a value here uh but let's say uh the month will be january um day will be first but uh i'm not sure exactly how to use this uh this one but let's let's say that we want to add here um today is 30 12 and 2020 and that should be it a temperature in celsius and a summary of course we can get away with zero and the summary would be mild winter okay and let's click on create forecast and we were redirected back here and we say that we have everything here so we have a record right now and uh yeah everything is fine uh the fahrenheit temperature was calculated automatically uh and then we can delete or update this entry let's create a new one and uh here let's uh let's have it for i don't know 30 but i don't know why let's have it's it's month okay so the month is first okay it's like that uh so it should be fine uh let's uh have the temperature this time i don't know about 20 and let's have it uh summary nice and create forecast we are redirected back and we have the list everything is fine so this component works again now uh of course what we need to do is also implement the update forecast and what we need to do here is actually exactly the same thing but let's say using microsoft dot empty framework core and let's uh inject the i db context factory of letter db context context factory okay and now uh the only thing that we should also let's inject navigation inject navigation manager and we should be fine with that now the only thing here that we have to do a little bit differently is that here on in this on initialized async we actually need to get an information about uh the forecast from the database uh in order to display it in the form because we want to update it or so it should already exist now what we can do here of course uh through navigation but we won't stick or we want to talk about how navigation works right now we get also the id of the weather forecast that we actually want to get so what we need to do here is of course also uh disusing and then of our context equals context factory create db context and this would create our context so first of all we don't need to create here an empty or a blank weather forecast because we will do this here forecast it would be equal to a weight context of forecasts of first or default async and then we'll provide of course where the forecast uh should have the id uh that we get also here in the routing and that would uh get our forecast for us and then here is actually on this component we can't see exactly how this really works with this idea of really creating a db context only when we need it and disposing it when we don't need it anymore because right now if we go here on this update the the thing that we actually want to do here is for instance that we can for we can do the following once again using and here uh we have again var we do exactly the same thing once again context uh factory but create db context so we have the context then what we can do here is uh we can say here for instance that we have uh context dot forecasts dot update and then we provide the forecast that we want to update then we await context save changes async and let should do it so right now actually we should be able to also update everything and let's also navigate to fetch data india navigation dot navigate to and we'll navigate to fetch data so everything should be fine so let's run the application and see if we can update the forecast in this case so let's it starts of course of the on the other screen but i will bring it right back here so if we go first on fetch data loading and we have this edit and yeah the form was open correctly and let's change here this from 15 to let's say 20 and let's click on update forecast and we see that it was updated and right now we are actually back here on the same one so let's edit this again and let's put in this case for instance i don't know it should be maybe 30 and let's see update and it updated correctly and let's add this the other one and i would say i don't know this one would be 35 and let's see update forecast and we see that everything updated correctly so right now also our update of forecast component works perfectly and of course the last thing that we would have to take care about is that delete operation and that's actually very very very easy and because if we go here in fetch data we have also here a method for deleting a certain forecast and that's actually very very easy and to make this as quick as possible let's just copy what we have here so what we'll get uh in this method is of course the id of the forecast that needs to be deleted so uh what we need to do here is of course we don't want to use the forecasts first of all but actually we get here the entire forecast that needs to be deleted so we will change this and for deleting instead of getting the id uh we just get the entire forecast it's actually easier like that uh and uh here delete forecast and we'll get a weather forecast and so we change things here on the fly but i still think that this is better to do it like that because what we can do here right now is we can simply say context of forecasts dot delete or remove sorry it's remove and we remove the forecast and what we'll do afterwards is await a context context.save change is async we want to do this asynchronously of course and what we'll do afterwards to trigger a re-render of everything we will call state has changed and yeah let's uh that should be it so let's run again and [Music] let's again bring the browser on the correct monitor for us to be able to see everything so let's go and fetch data so we're on fetch data and let's see if we want to delete this one so let's uh so we have deleted it [Music] but i guess that the status changed kind of in some somehow didn't exactly work but there is another thing that we can do maybe if the status change doesn't work right now what we can do is before we remove this actually from the database we go here in forecasts uh dot remove uh or how is it because this is an array this is not the list we can we cannot simply uh do this here okay so yeah unfortunately i'm not sure exactly this status change should trigger a re-render of of the entire ui but the idea is that yeah probably would have to to remove that forecast somehow but the the problem is here that we are working with an array it's it's not that easy to remove something from the array it's not a regular list for instance but i guess we won't spend any time right now to get into more details here so the idea is once again that we have here some very very basic crud and we have seen how we implement or how to use entity framework core with blazer server the right way but before we really wrap up this video became a lot longer than i would have expected initially but still i guess that it might be very very very important another thing that i would like to say or to mention as a best practice here so right now we have very short-lived db context and theoretically for i would say most of the application that shouldn't be a problem at all but it could be uh or there could be i don't know cases uh when maybe there is some competition between db context and and different things like that so another good thing to do when you are working with ef core in blazer server is let's add here another property let's call it private data loading uh it should be bull sorry so we use this actually as a certain or as a type of flag and for instance each time that we want to do something here with a db context we could actually use this for instance if uh data loading then we would simply return of course in a real application you would maybe log something display a message user whatever but here just return and then uh how we could do this is uh implement this try and of course we are moving this uh in this try block so let's uh ctrl x uh ctrl v and we moved everything uh in this try if we get an exception with row once again you can log you can do things but what is important here is that we add this finally uh and in this finally what we'll do and i guess that would be right now it would make a lot of sense for instance is that in the try before we start do anything with the db context we'll put the data loading on true in this case whenever i don't know maybe this method gets called once again while we do some work here we can just return and then of course in this finally uh we put the data loading flag back on false and this is once again a best practice a good pattern to use sorry when you use an entity framework or in a blazer server so yeah actually that should be it just as a short summary what we discussed in this video that that is a fairly long one but i think it's a very very important one is that when we work with blazer server and entity framework core we have an entirely new programming model because in blazer server we don't actually work with http requests anymore or not that much or in the majority of time we work with what we call a circuit in blazer server so once the user gets the app and that signalr connection gets gets initialized basically whatever happens in that application uh happens through that websockets connection and not through an http request and this in turn has the outcome that when we want to use the db context which is not tread safe the problem is if we add it normally with adb context it would be added it could get one instance per circuit and if we have several components that use that db context at the same time they would actually use the exact same instance of the db context and that would create problems so this is why we cannot use simply that sdb context so instead what we do we use this add db context factory and we inject this db context factory in our components like the fetch data component here we inject it via this interface idb context factory and then whenever we want to do something with database we create a new instance of that specific db context using the context factory and the createdb context method so in a nutshell this is how you need or how you should use entity framework core with blazer server the right way without having any other problems if you enjoy this content if you think it's useful please hit the thumbs up button that would be highly highly appreciated and if you didn't do already please subscribe it would be very very nice and you will be updated each time that we post a new video or each time that we go live to do some live coding and things like that and last but not least if you also i don't know have friends in your network or colleagues at work that you think they might find this content useful just don't be shy again and feel free to share it with your peers with your friends on your social networks and things like that it would be highly highly appreciated this being said thank you very much once again for watching this video and until the next time i wish you the very best
Info
Channel: Codewrinkles
Views: 15,964
Rating: undefined out of 5
Keywords: Blazor, Blazor Server, Blazor WebAssembly, EF Core, Entiti Framework Core, ASP.NET COre, .NET Core, .NET, programming, web development, C#, SQL, databases
Id: aaQsmkh1BkQ
Channel Id: undefined
Length: 33min 49sec (2029 seconds)
Published: Wed Dec 30 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.