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
Well done!
You have completed Entity Framework Data Concurrency!
You have completed Entity Framework Data Concurrency!
Preview
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