Setting Up Optimistic Concurrency6:23 with James Churchill
Let's see how to configure Entity Framework to use optimistic data concurrency controls.
Entities that we want to participate in our data concurrency control 0:00 need to define a tracking property. 0:04 The tracking property stores a unique value, 0:07 which is used to determine the version of an entity. 0:09 For every entity that defines a tracking property, EF will include its value 0:11 in every update, and delete statement that's generated for that entity type. 0:16 Later in this video we'll audit an update statement and see how exactly this works. 0:22 To configure EF to use optimistic concurrency, 0:27 let's start with adding a tracking property to the comic book entity class. 0:30 Located in the ComicBooks shared projects models folder. 0:34 You can name the tracking column whatever you like. 0:40 But a common name to use is RowVersion. 0:42 Then, we apply the TimeStamp attribute to this property. 0:55 Which we'll configure EF to use this property as a tracking column. 0:59 The timestamp attribute gets it's name from the timestamp database data type, 1:03 that older versions of SQL server used before it was deprecated and 1:08 replaced with the RowVersion data type. 1:12 You could only apply the timestamp attribute to one entity property. 1:15 If you apply the timestamp attribute to more than one property, 1:19 EF will throw an arrow. 1:23 EF enforces this restriction, 1:24 as each database table can only contain a single RowVersion column. 1:27 The corresponding .NET data type with a row version database data type is 1:32 a byte array. 1:36 The ComicBooks controllers edit post action method, 1:44 which handles form posts from the edit ComicBook page, 1:48 is bound to an instance of the ComicBooksEditViewModel viewModel class. 1:51 The ComicBooksEditViewModel class inherits from the ComicBooksBaseViewModel class, 1:57 Which defines a comic book entity property. 2:04 The comic book entity properties are populated by MVCs model binding 2:07 using the values posted from the HTML form on the Edit Comic Book page. 2:12 Now that the ComicBook entity has a tracking property, we need to update 2:17 the partial view that renders the form to include the tracking property value. 2:21 If we don't do this, 2:26 the ComicBook entity's tracking property value would be null. 2:27 When processing a user's form post in the controllers, edit post action method. 2:30 And no tracking property value would cause the ComicBook update to fail. 2:36 The tracking property value is a system concern, meaning that while it's something 2:41 that's required for our Web app to function properly, 2:45 it's not something that our users either would care to see or would want to edit. 2:48 Given that, we can render the tracking property's value to the form using 2:52 the HiddenFor HTML helper method, which will render a hidden field. 2:57 You can think of the hidden field as a regular text field, 3:02 that is hidden from the user so they can't easily edit it's value. 3:05 I say easily because a savvy user can use the browsers to develop 3:09 a tool to change the value of the hidden field. 3:13 So it's not a secure way to round trip sensitive data between the server and 3:17 client. 3:23 That being said, in this specific case we're not concerned about a user hacking 3:23 the tracking property value. 3:28 So it's a convenient method that we can use. 3:30 Before we test our changes lets update the contexts database log property. 3:32 To a lambda that will write messages to the output window. 3:39 The context is instantiated in the constructor for the base controller class. 3:43 Which is the base class for each controller in our web app. 3:48 This will give us a way to audit the SQL queries in commands that EF generates and 3:50 executes. 3:56 With that last change in place, let's test our changes. 3:58 EF will detect our model change and invoke our database initializer, 4:04 which will drop and create the database. 4:08 If it exists, if the database doesn't exist, then EF will just create it. 4:11 We can use the SQL Server Object Explorer to verify that the ComicBook table now 4:16 includes a row version column with a data type of RowVersion. 4:21 And here's our new column. 4:31 Now let's test our data concurrency control by opening the Edit Comic Book 4:35 page into two tabs for Bone #3. 4:40 Save the first tab. 4:47 Then Save the second tab. 4:52 And we get an exception. 4:59 SystemData.Entity.InfrustructureDbUpdateC- oncurrencyException. 5:01 Store update, insert, or delete statement, effected in unexpected number of rows. 5:07 Entities may have been modified or deleted since entities were loaded. 5:12 In the output window, we can see the SQL update statement that EF generated and 5:21 executed. 5:26 Notice how EF is including the RowVersion column in the WHERE clause. 5:30 When EF detects that a tracking property is present on an entity, 5:34 it'll include its value in every generated update and delete statement. 5:38 That guarantees that an update or 5:43 delete will only succeed if the tracking column value matches. 5:45 If an update or delete doesn't effect any rows, 5:49 meaning that a row wasn't found that contained the provided ID and 5:52 row version column values, then EF or throw a DbUpdateConrrencyException. 5:57 The database will update a rows tracking column value 6:04 every time the row is updated. 6:07 So if some one updates record in between the time that we retrieve a record and 6:09 attempt an update, all update will fail. 6:14 By not allowing our update EF ensures that the data stays in a consistent state. 6:17
You need to sign up for Treehouse in order to download course files.Sign up