This workshop will be retired on May 1, 2025.
Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Preview
Start a free Courses trial
to watch this video
Let's see how to configure Entity Framework to use optimistic data concurrency controls.
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
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 upYou need to sign up for Treehouse in order to set up Workspace
Sign up