Updating Entities9:12 with James Churchill
Let's look at updating entities. Specifically, updating ComicBook entities in the Repository class' `UpdateComicBook` method.
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/v5.3 -b updating-entities
Let's look at updating entities, specifically updating 0:00 comic book entities in the repository classes UpdateComicBook method. 0:03 As mentioned in the previous video, 0:12 EF tracks the changes to entities that are loaded into the context. 0:14 The UpdateComicBook method is past an instance of a comic book entity, but 0:18 that entity is not being tracked by the context. 0:23 Entities that are not being tracked by the context are said to be disconnected or 0:26 detached. 0:31 There are a number of ways that we can persist data changes contained within 0:33 disconnected or detached entities. 0:36 Our first option is to retrieve the entity from the database. 0:39 Then write code to manually update the property values. 0:43 To retrieve the entity, we can use the DB set find method. 0:47 Don't forget, we need to start with getting an instance of the context. 0:52 Using (Context context 0:55 = GetContext()). 1:01 Then we can retrieve the comic book, 1:06 ComicBook comicBookToUpdate= 1:12 Context.ComicBooks.Find(comicBook.Id). 1:17 Then we simply update the retrieved entity property values with the values from 1:26 the passed in entity. 1:31 comicBookToUpdate.SeriesId = comicBook.seriesId. 1:35 comicBookToUpdate.IssueNumber = 1:43 comicBook.IssueNumber. 1:49 comicBookToUpdate.Descriptions = 1:54 comicBook.Description. 2:02 comicBookToUpdate.PublishedOn = 2:07 comicBook.PublishedOn. 2:12 And then comicBookToUpdate.AverageRating 2:17 = comicBook.AverageRating, and call the SaveChanges method. 2:24 When we call the SaveChanges method, 2:33 EF will detect the changes to the entity that is being tracked in the context. 2:35 Generate a sequel update statement and 2:40 execute that statement against the database. 2:43 All this approach is simple and 2:46 easy to understand, it's tedious to write and maintain. 2:48 Let's look at another option. 2:52 In this option, 2:56 we still use the DB set find method to retrieve the entity from the database. 2:57 But instead of manually setting the new property values, 3:02 we retrieve the entity's entry from the context. 3:06 And call the current value's set values method to copy the passed in entity's 3:09 property values to the entry's current values collection. 3:14 context.Entry(ComicBookToUpdate).CurrentV- 3:17 alues.SetValues, then pass 3:25 in the (comicBook) parameter. 3:30 After calling the sub values method, the entity state assuming that at least 3:35 one property value is updated, will be set to modified. 3:40 A state of modified indicates that the entity has a change 3:44 that hasn't been persisted to the database. 3:48 When we call the SaveChanges method, EF will generate a SQL update statement for 3:51 the modified entity and execute that statement against the database. 3:56 Let's test our changes. 4:00 Set a break point just after the call to the save changes method and run the app. 4:02 Enter 3 to view the detail for issue number 3 of the bone series. 4:12 Then enter U to update the comic book. 4:17 Let's change the average rating. 4:21 Enter 5 to select a property, then enter 7 for the value. 4:23 Enter S to save the comic book. 4:30 Now, we're at our break point. 4:34 The save changes method was just called. 4:36 In the output window, we can see the queries that were generated and executed. 4:50 The first query was the query to retrieve the comic book entity. 4:55 And the second query was to update the average rating column. 5:06 This option is an improvement over the first. 5:10 And that we don't have to manually update the entity properties. 5:13 A downside to both approaches is that we have to retrieve the entity 5:17 from the database. 5:20 Which means that updating an entity requires two queries. 5:22 One to retrieve the entity and 5:26 another to persist any changes to the entity to the database. 5:28 Let's look at an option that doesn't require two queries. 5:37 Instead of retrieving the entity from the database, 5:41 we can attach the passed-in entity to the context using the DB set attach method. 5:44 context.ComicBooks.Attach(comicBook). 5:50 After attaching the entity to the context, its state will be set to unchanged. 5:59 EF is unable to detect whether or not any of the entity's property values 6:04 are different from the values that are currently in the database. 6:09 We can force EF to treat the entity's values as new 6:13 values by setting the associated entry state to modified. 6:17 context.Entry(comicBook).State = EntityState.Modified. 6:22 Now, when we call the SaveChanges method, 6:34 EF will persist each of the entity's property values to the database. 6:37 Let's test our changes again. 6:41 Enter 3 to view the detail for issue number 3 of the bone series. 6:47 Then enter U to update the comic book. 6:53 Let's change the description. 6:56 Enter 3 to select the property. 6:58 This is my new description. 7:02 Then enter S to save the comic book. 7:08 We're at our break point again, just after the SaveChanges method call. 7:12 In the output window, we can see the query that was generated and executed. 7:17 So we were able to eliminate the query to retrieve the entity from the database. 7:25 But on the downside, as we can see in the generated query, 7:30 every column value is being updated in the database. 7:34 Not just the ones that have actually changed. 7:37 In most situations, this approach works fine. 7:44 Though, there might be times that an entity contains a property that shouldn't 7:47 ever be updated. 7:52 Let's imagine that once a comic book has been added to the database, 7:53 its issue number shouldn't be changed. 7:56 Let's start with rewriting this line of code, so 8:00 that we retrieve the current books entry into a variable. 8:03 Var comicBookEntry = context.Entry(comicBook). 8:09 Then, comicBookEntry.State 8:21 = EntityState.Modified. 8:26 Then use the entries property method 8:31 to get a reference to the issued number properties entry object. 8:33 And set the entries is modified property to false. 8:37 comicBookEntry.Property("IssueNumber").Is- 8:42 Modified = false;. 8:50 This line of code will prevent the IssueNumber property from being included 8:54 in the generated SQL update query. 8:58 Go ahead and remove or comment out this line of code. 9:00 We want our users to be able to change a comicBook's issue number. 9:04 After a code challenge, we'll see how to delete entities 9:08
You need to sign up for Treehouse in order to download course files.Sign up