Loading Related Entities11:05 with James Churchill
So far in this course, we've eagerly loaded related entities using the `Include` method. Let's take a look at the other two options—lazy and explicit loading to see how they compare.
To follow along commiting your changes to this course, you'll need to fork the dotnet-comic-book-gallery-model repo. Then you can clone, commit, and push your changes to your fork like this:
git clone <your-fork> cd dotnet-comic-book-gallery-model git checkout tags/v4.4 -b loading-related-entities
When retrieving entities it's common to need to load entities that are related to 0:00 the main entity that you're interested in. 0:04 For instance, in the previous section when we executed a query to retrieve a list 0:06 of comic books, we also needed to load the related artist and 0:11 role entities for each comic book in the list. 0:15 EF supports three methods for loading related entities. 0:18 When eagerly loading related entities, 0:23 you can write a single query that not only retrieves the data for 0:25 the main entity, but also the data for the related entities. 0:29 The include method is used to tell EF which related entities to load. 0:33 With lazy loading the related entities 0:38 are not loaded until their navigation properties are accessed. 0:40 The process of lazily loading related entities is automatically handled by EF so 0:45 it can seem like magic the first time that you see it in action. 0:51 As an alternative to lazy loading 0:55 you can also explicitly load related entities using the load method. 0:57 So far in this course, 1:02 we've eagerly loaded related entities using the include method. 1:04 Let's take a look at the other two options, lazy and 1:08 explicit loading to see how they compare. 1:11 If you're following along, 1:14 let's start with removing the changes from the previous video. 1:16 Here's the original query that we were using to retrieve the list of comic books. 1:31 These three include method calls tell EF to eagerly load the series, 1:36 comic book artist, artist and role entities. 1:41 Let's switch to using lazy loading. 1:45 First, let's comment out these three lines of code. 1:48 Second, we need to update the comic book and 1:52 comic book artist entity navigation properties to be virtual. 1:55 We do that by adding the virtual keyword in between the properties access 2:00 modifier and the data type. 2:05 And then the ComicBookArtist entity. 2:13 Let's run the app and see if we still get the expected output. 2:32 And, here's our list of comic books, artists, and their roles. 2:36 So how does lazy loading work? 2:41 When the in memory representation of our model is being created at runtime 2:45 EF will detect that our navigation properties are marked as virtual and 2:49 create subclasses for those entities. 2:53 Within those subclasses, EF will override our navigation properties. 2:56 The overridden properties give EF the ability to detect when those properties 3:00 are accessed, and retrieve the data for those properties when it's needed. 3:05 The derived entity types that EF creates are called Dynamic Proxies. 3:10 Let's run our app again, but this time we'll set a break point 3:17 at the beginning of our foreach loop so we can inspect the collection of comic books. 3:20 Here we are at our break point. 3:33 I hover over the comicBooks variable 3:34 to see a preview of the objects in the collection. 3:37 Normally we'd expect the value of the items in our collection 3:41 to be the fully qualified type name for the ComicBook entity class. 3:45 Which are case is, ComicBookGalleryModel.models.ComicBook. 3:49 But with lazy loading enabled, the type name is 3:54 System.Data.Entity.DynamicProxies.Comic- Book 3:57 followed by a long string of letters and numbers. 4:03 The long string of letters and numbers is a hash of a generated description for 4:06 the entity that's been subclassed. 4:11 Go ahead and remove the break point and press F5 to continue execution. 4:14 Now let's look at the queries that were executed by EF to retrieve the data for 4:23 our application. 4:27 Remember when we were eagerly loading related entities 4:29 EF executed a single query to retrieve the necessary data. 4:32 With lazy loading enabled multiple queries are needed in order to retrieve the data. 4:37 Here's the first query, 4:54 the query that EF executed to retrieve the list of ComicBooks. 4:55 The second query is to load the ComicBookArtist entities for 5:02 the first comic book that was enumerated in our foreach loop. 5:06 Notice in the query right here, we can see that we're filtering to the rows 5:12 who's comic book ID column values are equal to something named @EntityKeyValue1. 5:18 @EntityKeyValue1 is a sequel parameter. 5:24 In the comment below that we can see that the EntityKeyValue1 parameter value 5:29 was 1, which is the primary key value for the first comic book in the list. 5:34 The next four queries are to get the related artist and role entities, for 5:39 the first comic book artist entity. 5:43 Here's the query to get artist Id1. 5:46 And role Id1. 5:52 Artist Id2. 5:57 And role Id2. 6:01 The comic book artist, artist, and roll entities need to be loaded in order 6:02 to get the displayed text for the comic book artists and their associated rolls. 6:08 The next query is to load the Series entity. 6:16 The Series entity needs to be loaded in order to get the displayed text property 6:19 value which is a combination of the series title property and 6:22 the comic book issue number property. 6:26 The next query is to get the ComicBookArtist entities for the comic 6:29 book with an Id of two which is the second comic book in our comic books collection. 6:33 Then the next query is to get the ComicBookArtist entities for 6:41 the comic book with an Id of three. 6:45 What happened to the queries to get the related Artist and Role entities for 6:48 the second comic book? 6:52 Since those entities are the same as the entities for 6:54 the first comic book they're already loaded into the context. 6:57 EF is able to detect this and associate those entities 7:01 with the second comic book without having to retrieve the data a second time. 7:05 Now let's look at the third option for loading related entities. 7:13 Explicit loading. 7:17 To demonstrate explicit loading, 7:20 let's remove the virtual keyword from the comic book series navigation property. 7:22 Now that we're not eagerly or lazy loading the series navigation property, 7:28 the coming book displayed text properties should not work properly. 7:33 And sure enough, we're just seeing that issue number for each comic book. 7:37 To explicitly load the series navigation property, let's add an if statement just 7:48 inside of the foreach loop that checks if the comic book series property is null. 7:52 If comicBook.Series == null. 7:57 If the property is null then we'll call the context 8:02 as entry method passing in the current comicbook context.Entry(comicBook).. 8:07 The entry method returns a db entity entry object for the referenced entity. 8:16 Every entity that has been materialized and 8:22 tracked by the context has a db entity entry object associated with it. 8:25 This object exposes two methods that we can use to get the entry objects for 8:31 navigation properties. 8:35 Reference for non-collection navigation properties and 8:40 collection, for navigation collection properties. 8:45 The entry objects that are returned by these methods provide a load method 8:50 that when called, will load the related entity's. 8:54 Since the series property is a non-collection navigation property, 8:58 we'll use the reference method to get the entry for the navigation property. 9:02 Cb => cb.Series. 9:11 Then we'll call load on the returned object. 9:22 .Load();. 9:25 Calling the load method will execute a query against the database 9:29 every time that it's called. 9:32 That's why we need to check if the series is null and 9:34 only call the load method if we need to, 9:37 otherwise we'd end up executing queries for entities that were already loaded. 9:40 Now let's test our explicit loading of the series entities. 9:45 And our output is back to what it should be. 9:49 Let's take a look at the pros and cons of each approach for 9:54 loading related entities. 9:57 When you see Eager Loading, 9:59 there will generally be fewer queries executed against the database. 10:01 There are also be fewer surprises as it forces you to plan upfront 10:05 with data you'll need for your application. 10:10 Of the three options, 10:13 Lazy Loading is the easiest to use plus you only load the data that you need. 10:14 On the downside, 10:20 as we saw in this video, Lazy Loading can result in a lot of queries. 10:22 Explicit Loading gives you exact control over the loading process. 10:27 Additionally, though we didn't demonstrate it, you can load just part 10:31 of a related collection which isn't possible with Eager or Lazy Loading. 10:36 The challenge with explicit loading is that it requires 10:42 more thought and planning. 10:45 I tend to find that I use eager loading more than the other options. 10:47 It's relatively easy to use and I like its explicitness. 10:51 That being said, every situation is different so consider the tradeoffs of 10:55 each option and pick the one that is the best fit for your particular situation. 11:00
You need to sign up for Treehouse in order to download course files.Sign up