Entity Framework Core 5.0: The Next Generation for Data Access

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
our next session is with jeremy likness and shire bojonsky and they're going to talk to us about enemy framework core 5 the next generation for data access hello and thanks for the welcome hello everybody my name is jeremy i'm a.net i'm a program manager on the.net data team i'm here with shai shai yeah so i'm shi rojanski i'm an engineer on the efcor team awesome so we are bringing to you ef core 5 which is the feature complete release that we just announced this morning super excited to share with you some of the new features that are coming down the pipeline first for those of you not familiar with entity framework i have a quick and general introduction what is ef core and why should i even care so at the end of the day entity framework core is a data access api it's an object relational mapper and we put that in parentheses because we also support non-relational databases like azure cosmos db we target.net standard 2.1 which means anywhere.net standard 2.1 is you can use entity framework core that's your blazer xamarin asp.net core wpf winforms it's across the spectrum at microsoft we support sql server which includes azure sql server sqlite and azure cosmos db but there are many other databases that are supported both by the community and other companies you can see that list at the link here aka ms ef core providers one of the benefits of using ef core is that you can use the strongly typed query integrated language or language integrated query i should say link to specify your queries we're going to show you examples of that we also implement unit of work out of the box so entity framework core will track changes and even handle concurrency for you finally it's data binding friendly out of the box so if you're using wpf or winforms for example as data binding frameworks it plays very friendly with those so let's take a look at the the basics really quickly here is a plain old c sharp object i have a class that has some data annotations these are probably so that a form can display the right messages etc out of the box into the framework we'll look at this and instantly assume id is a primary key it has certain conventions that are built in but you can override those everything is configurable here we have data annotations these are optional but when they're present if you're using any framework core to generate your database it'll take hints from these for example the size of the column whether or not the column is nullable or not now i've added what's called a navigation property from this entity i'm referencing a set of other entities any framework will automatically understand that this needs to set up a relationship to other entities everything starts with something we call the data context or the db context i say that's where all the fun happens this is how we really describe the interface between data and our c-sharp domain or our f-sharp domain any of your that net applications so here we're injecting some runtime configuration we'll talk more about what that looks like this is a db set the db set is how you tell entity framework that here's an entry point to start mapping an entity to the backend database we also have fluent mapping with uh what we call the model builder so for example i might not want to keep a timestamp on my class because it's not needed in my application but i do need it in the database for concurrency so here i'm creating what's called a shadow property which is a property that entity framework will track without us having to have an explicit property on the entity and here we're telling it that this is a property you use for concurrency and i'll show you what that looks like so let's configure a data context i'm in an asp.net core application i'm adding my dependency injection services here i'm configuring a factory our recommendation in asp.net core and blazer apps is to create a data context for operation it's very lightweight to generate one of these so this factory will give us a mechanism to obtain new instances and here we're configuring it to use sqlite and sqlite takes a very simple connection string it's just the path to the file if this was sql server i could pull this from environment from secrets from key vault etc and pass that in now i have my data contacts i want to query something here i'm creating the context using my factory and then i'm asking for a list of contacts with some filter this is link syntax it's filtering city ordering skipping taking etc and what that turns into is an actual query now this is sqlite it will look different for sql server or for other database providers but that's part of what entity framework does for you is it makes that translation based on where you're running the query let's take another example i want to update a contact so here i'm grabbing a contact from the data context and because i get it from that interface entity framework is constantly tracking it and watching for changes so notice i'm just changing two properties on that class and then i'm saving changes in any framework is going to be smart enough just to update those two columns but it's also grabbing that row version so that we use what's called optimistic concurrency if that record isn't hit we know it's changed underneath the scene so we can handle that scenario so now that's your five thousand foot rapid pace introduction in any framework let's talk about some of the new improved and exciting features i'm gonna jump into a demo that covers some of the diagnostics features so let me pop over to my.net 5 application so here i've got a class called something because i wanted to demo something for you and i mentioned that we need a db contact so this is a db context that i'm configuring it's pretty simple we're just attaching some things and we're injecting these options for configuration if i come back to the top i've got a top level application i'm creating a connection string i have a database setup so if you run this sample yourself it's going to go ahead and populate it with some data we're going to show some counts and then down here we have a query that's filtering for active things that were created in the past week and then it's using something called a projection we don't need all of the properties on that class so we're just asking for these two properties so let's go ahead and run this make sure our live demo is ready to go so it says it's ready so notice i have ten thousand things and it's pulled five because of the take five and here we've got our dates etc now let's say i'm not trusting the system maybe there's a problem with my query maybe i want to make sure we didn't pull back 10 000 things and then filter them that way because that would be inefficient what are my options to troubleshoot and dig into this well the first one i want to show you is just as simple as debugging your application so i'm going to set a breakpoint jump into debug we'll let it run to this breakpoint give it just a second here so now we're in the break point i'm going to hover over this query and show you something that is specific to the framework which is this debug view if i expand this debug view i get an expression which is going to be the programmatic syntax for the query so no matter how it was built up it's going to be finalized in this expression the other thing i can show you is down here let me hover over again debug view we have this query and if i open this this is the actual query that's going to be sent to the database now again this is sql light syntax if you're using sql server this would be sql server syntax but you could paste this into a management console and run it as is so that gives you a straightforward way to troubleshoot but let's assume that i don't want to just debug interactively because that doesn't scale i want another way of grabbing that that query well we've got a special extension method called let's do query 2 query string and this will actually analyze that query and produce the string that's going to be sent to the database so i'm just going to do a console.writeline with query str here let's go ahead and run this again and of course the builds gonna take a second so i'll spin my mouse bring this over now notice right here we got that exact same thing we saw in the debug view this is the actual query that's being sent to the database right here with the parameters and everything so that's another way that we can view it but i want to show you one last way that we've simplified diagnostics so we've always had support for loggers and this is the logger factory logger providers etc but we added a new option to make very simple logging and that's called log2 and what log 2 does is it takes an action that takes a string so i'm just going to go ahead and send it straight to console.writeline and it also takes a logging level so we'll do log level i'll do information and that's all of the configuration i need to add this new simple logging i'm going to run this in debug one last time hit enter blow through my break point and find my application here so now we've got a lot of information we see that the db context was initialized we even have this warning that tells me i used to take without using an order by and for some databases that can produce inconsistent results i might get random five records because i didn't order them before so it gives me those detailed warnings then i get the query then i get the results so this is a way if you have issues with your applications or you just want to understand what's going on behind the scenes you have several options to peek behind the curtain if you will and see what's going on so now having covered that i'm going to turn it over to shai who's going to look into some of the new what we call mapping features mini to mini table per type and show you an awesome demo of how these features look shall i take it away yeah so um hi everyone i'm shai i'm an engineer on the efcor team so the first feature i'm going to cover here is uh something that users have been asking for for quite a while and that's improved support from many to many now anybody who's done a bit of database programming knows about many-to-many it's quite simple let's say you have a bunch of users here and you got a bunch of groups here many of the many is that is the fact that your one user can belong to multiple groups and the same group can also have multiple users right so hence the name many to many right the way you do this in a relational database is you stick a table in the middle we call this the join table or the association table and each row in that table in the middle is going to link up one user to one group so much for the theory now obviously you could you could have done many to many before ef core5 came along otherwise it would not be a very good uh you know database access layer however there's a lot of cool things coming for 5.0 so i'm going to first show how things used to be done in could be done before and then i'll show the new nifty stuff so we can finally look look at some code very quickly so what we have is a very kind of classical and easy ef model so we've got a user with an id and a name we've got a group with an idea the name and we have this thing the membership which represents the thing in the middle a membership has one user in one group and it represents the linking the this association that we were talking about if we scroll up we've got uh you know the db context that jeremy was mentioning this is a very standard run-of-the-mill one using the log2 that jeremy also demoed and up here we've got a bit of data to make things interesting so we've got uh john jane and john as users we got a football group and a movies group and we're gonna do some memberships so jane and john they like football they're in that group jane likes movies but john doesn't apparently we throw all that into the database and save it it's that easy to do things with eve core and here we're gonna just see a quick query to make this interesting so we're basically going to query for all the users which have any membership whose group name is movies so we're querying out basically users which are members of a group called movies let's do a quick run through this to see what comes out so i'm using that simple logging thing to look inspect the sequel exactly as jeremy here told us so scrolling up i can see that we're creating a groups table we're creating a users table and a memberships table everything is pretty straightforward the thing to note here is that for each.net class that we have in our ef model we have a table so it's a very simple correspondence kind of thing if we scroll down here we're going to see the actual query below it doesn't really matter i'm not going to go into the sql the important thing is that we're going to see us producing the same thing later with uh with uh different things great at this point so i'm a software engineer right so the thing i like most in the world is obviously writing code there is just one thing i like even more than writing code and that's the leading code so the best thing in the world is when you've got a feature that allows you to remove like a swaths of code and and your program you know continues running like before there's nothing better for a software engineer so what we're going to do now is switch over to ef core 5 mode and we're going to do precisely that the thing with memberships here is that we don't really care about it memberships is just a detail it's the join table it's a detail about how the many to menu is implemented in a database but in our c-sharp programming world we don't really want to care about it so much so what i'm going to do is escort five let's say bye-bye to that one and we're simply gonna go and have navigations from the group directly to the users we're going to do the exact same thing the opposite direction so this is exactly how we want to model things right i mean users have groups and groups of users we don't care about how that gets implemented behind the scenes if we scroll up of course we no longer have membership so our seating is going to change a little bit all we have to do here is to see the users on their groups on the groups themselves so that's going to clean up quite a bit of code um same thing for the movies but i think we had only jane in the movie lovers category and now we've seen it done so we don't need all this look at all this lovely code going away we're left with this and obviously the query itself has to be tweaked a bit so there's no more memberships but we've got something better we got the groups directly so i'm going to just query the groups directly here i'm going to change this identifier and we've got a much lovelier query right because it now says exactly what we wanted to say get the users where any of the groups has a name of movies okay so we've removed all this code we're going to run this again after having changed all this and the thing to note if i scroll up is we still have those three tables here groups users and group user so this a bit of magic efcor has basically looked at this we no longer have um a.net type for this that's why it's named group user by the way or not membership but if core has understood implicitly that we want a many-to-many mapping and it's created the joint table for us so we don't have to explicitly mess with those details right and that's pretty cool if you look down here below then you have the same the same actual query so in fact nothing has changed in the database behind the scenes the only thing that happened is that we made our c sharp code much much easier and it's worth maybe stating that you know we have users and groups memberships are nowhere to be found but they're there in the background right we are skipping over them okay that's that's the that's the thing the important thing to know now this is already pretty cool and ef actually did this if if entity framework six actually did what you've just seen so if cornell does that too but we actually took it a step further in efcor and that's pretty cool so what we've what we realize is that pretty soon after you do something like this your customer or some pesky manager maybe is going to come along and they're going to ask to to store some sort of data on the association they're going to want to know something about that link between users and groups for example let's say we want to know when a user joined a group so we want to attach what we call a payload property to that many-to-many association now if we want to do this we're going to bring back a little bit of code which you just saw me um you know taking out but it will still be very cool indian trust me on this so we're going to have a membership type here again that represents um you know the join entity here we're going to bring back the collection of memberships just like it was before but the thing to note and that's very important is that we're going to keep the users here that's the key that i'm going to talk about in a second so we have both memberships and users or groups here now to make this actually interesting i'm also going to pull in a query um sorry there's one more thing i have to do before that so i'm going to put in a little bit of configuration so this thing don't be afraid it's actually very simple and straightforward it's us configuring ef core saying each user has many groups and each group also has many users so that's an explicit configuration of the many-to-many that was implicit before and we're instructing efcor to use memberships as the join entity so we've basically gone back to exactly what we just had only we're doing things very explicitly if we i'm going to do this very quickly if we again run this program then we're still going to see the same query and we're going to see the same three tables this is a super boring demo because they keep showing the same sequel but it is you're going to see it's going to be quite interesting so the thing is is once i've done this and reintroduced membership now i can introduce my payload which is member sense a timestamp for when the member joined the group and now i'm going to pull in this quick query just to show you that i can and our query is to take all the users where any of the membership they've been a member of since 2 2000. so basically we're querying for old timers for people who've been members since 2000 maybe because we want to send them a gift bag or something similar now i'm not going to run this because the actual query isn't very interesting but the really really really cool part here is that in this query we indeed are referencing the join entity and we're looking at the payload property but right here we still have our old query which doesn't care about it this old query still skips over the memberships table or entity and goes directly from users to groups and we don't have to mess with those details so escort doesn't force you now if or five doesn't force you to deal with that detail in the middle it just lets you skip over that property if uh that that table that joint table and you know cleans up your code so that's a pretty good feature at least we think so and with that i'm gonna jump to my second uh feature which is a new way of doing inheritance uh mapping with efcor so inheritance mapping uh is basically what this means is that you have a hierarchy of dotnet types right like a normal hierarchy um base class subclass all that kind of stuff and you want to map that to a relational database that's not trivial now efcor has once again supported doing this since the very beginning but if core5 introduces a new way to do this so i'm going to quickly go through how this used to be done in ef core before five and then we'll see the good stuff so i'm just gonna pull in a new code sample it's very simple to the previous one we've got user and group we still have the same many-to-many uh relationship but now if you look at this our user has a subclass called external user with an external company property and there's also a time restricted user with some other other properties we don't care about so all these we want to map to the database it's quite a feat now the fact we added these entities which are subclasses doesn't automatically make efcor map them to the database i have to have these two little things here which basically let efcor know about these two subclasses and it lets ifcor know that i want if to map these if we scroll all the way up here then we see that john has been converted to an external user uh who comes from an external uh company called foo and the query is really really quite simple we're basically going to query for all external users here uh whose external company is foo all right so i hope that's that's clear so i'm just going to hit run on this reminder again that this is not ef core this is not specific to ef core5 what i'm saying what i'm showing you now if we go up here and we look you know we have our the table creation um sql we see something strange our users table has morphed it's unrecognizable now it has these weird properties on it so it's got external companies start time and end time so what's actually happened is of course walked our hierarchy it looked at these three donna types if they came out it's kind of like pulled out all of these properties and put them in a single table in your database it's basically folded an entire hierarchy into a table so this this strategy we call table per hierarchy because there's one table for an entire hierarchy or tph and that's been supported since the beginning of ef core uh now one thing that this mapping strategy uh one problem with this strategy is how do you know which row corresponds to which type of user so you look at a specific rule is that an external user just a normal user so because of this what efcor does it adds an invisible column we don't have to deal with this in our code it adds a discriminator whose sole purpose is exactly that it tells you if you look at it it will tell you this is an external user or this is a time restricted user or whatever if we scroll down below to look at our query query is very straightforward so we're going to query the table users and we're going to look only for rows where the discriminator is external user because that's what we want in link and we're going to filter by the company so far so good so this is the way uh that you that the only way that you could do this in ef 3.1 for example now ef core5 allows you to do a little bit of magic here a kind of a new feature so what i'm going to do is i'm going to add a quick directive on the subclass entity which is to map it to a different table so each one of these guys are going to be mapped to a different table that's all the code i'm going to change it's that small that simple and i'm going to run this again and you're going to see some pretty different results so if i go up here you can see that my user stable has conv become very thin again it's gone back to normal right normal size however when we've now added external users right along it alongside it and we have external company on it and down below we're also going to see time restricted users and so on so what we have now is basically a table that matches every type that we have in our hierarchy we call this table per type or tpt that's the new ef core feature the really important thing to notice here is that if you look at one single external user like john if we look at john john is spread across two different tables his name is in the base table users and his external company is in another table that has some very important consequences if we scroll down below and we look at the query it's very different from our tph query now what we are doing is querying users and joining with the external users table we have to pull in data from two different tables because that's the way tbt works right that's what we asked for and of course we apply the filter so uh stepping back a bit a lot of people have been asking for this because sometimes it fits their scenarios it's also simple to understand because every class in your.net model is going to have a corresponding table so far so good however it turns out that databases for databases performing a join is not a trivial thing it can be quite hard so a join is actually can actually be a source of a lot of performance issues imagine that you don't have two tables here but you have a very deep priority that means that we're gonna have to join a lot of tables here like five joins or something like this if you're joining five tables just to get john out then that's potentially gonna be a big performance problem this is why we've introduced this feature but what we're telling people our users is to still prefer the old or the the existing tph um mapping strategy by default it's perfectly fine to switch to tpd that's why we introduced it but we really recommend investigating perth and you know making sure you understand exactly what you're doing perfwise before you use tpt and that's about it and with that i think i'm going to give it back to you jeremy thanks and that's a great point don't take anyone's word for performance always test your application see what's happening so take a quick look at the the link aka dot msef docs that'll take you to our documentation we rolled out an entirely new documentation site to cover all these new features and reorganized it so we look forward to you visiting trying it out and giving your feedback and i think we'll look at some questions maybe yeah we have some questions thank you so much jeremy and shai that was an awesome awesome session uh lots of folks have questions so here's one of the first ones that we got and we got a lot of questions around this um this is from sergio he wants to know can i use records from c sharp nine for creating models in entity five yeah i can probably answer to that so we we've added a little bit of support for um you know records from c sharp nine but the problem with records uh is exactly their strength is so records are immutable by definition right so the problem with the effort is that in general you're going to query something from the database you get your you know you get an instance and then you're going to modify it and as jeremy showed before change tracking this automatic thing that efcor does is going to automatically detect the changes and save them back to the database but with records you're not mutating the instance that you got back from me of course you're creating a copy so efcor doesn't have any way of knowing uh that you've actually made those changes having said that this is something that's very much on on our radar and we have some some crazy ideas about how to make this work but um i wouldn't i would say that right now it's not necessarily the you know of a well-supported strategy at least if you're doing change tracking if what you want is to change track like you usually do yeah okay uh let's see if we have time just for one more question let's see uh let's see what other ones we have here oh records yeah exactly uh what about this one from greece trip uh it does ef45 support database first design yeah so uh what ef has supported what what can be called database for like not just from ef core five so what ef core does is it allows you to scaffold or sometimes we say reverse engineer um an existing database that means that you point it at an existing database that's going to look through your database discover your schema and produce a code model from that so that's a sort of a database a database first kind of flow what happens then can vary so you can just take that and turn that into a code first so you can evolve that now in code or you can continuously reverse engineer so your database can be your source of truth and then every time you reverse engineer that into your uh back into code and you can even use partials to evolve that you know better we have again some ideas about how to make the database first even stronger in the future but yes so the quick answer is yes and that's actually not a new feature in ef45 it's been improved but it's been there also before cool awesome well thank you so much jeremy and shy uh we're gonna you know get ready for our next session that we have coming up so thank you again
Info
Channel: dotNET
Views: 106,190
Rating: 4.9482679 out of 5
Keywords: .NET
Id: BIImyq8qaD4
Channel Id: undefined
Length: 28min 44sec (1724 seconds)
Published: Thu Nov 12 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.