>> On today's Visual Studio Toolbox,
Phil is going to show us how to handle concurrency issues.
So in other words, what happens if two people change
the same data at the same time?
[MUSIC]
>> Hi, welcome to Visual Studio Toolbox.
I'm your host, Robert Green,
and joining me today is Phil Japikse. Hello, Phil.
>> Hi, Robert.
>> We are now in part, let me check my notes,
6 of our Entity Framework Core In-Depth series.
Today, we're going to talk about concurrency.
>> Correct.
>> Concurrency is a common problem with software.
For example, I'm looking at a particular record,
you're looking at a particular record,
we both pull the data back and we're both going to edit it.
We're editing the same field to different fields,
if I make a change and then save it,
and then you make a change,
you're changing the data
from where it was and you're going to overwrite my changes.
So concurrency, we've dealt with this for years.
The problem is how do you know when it happens?
Then the business decision is what do you do when it does happen?
>> I would imagine that you spend way
more time trying to figure out
the rule than you do in code to implement it. Is that true?
>> Yeah. Because the simple thing is first one in wins.
But from the business standpoint,
they might not understand,
like if I'm changing the color of a car
and you're changing the make of the car,
we're not really having a conflict.
So there is a row-level concurrency
and there is field-level concurrency.
Now row-level concurrency is seldom.
Field level concurrency is a lot of programming.
Fortunately, EF Core makes that much easier for us.
So it's not something that I will fight so
hard against now as I did in the past.
So should we jump in and see how easy it is to
concurrency checking in EF Core?
>> Let's do that.
>> So let me share my screen here.
So here's my timestamp.
We've mentioned it in a couple of shows
already that the timestamp is the trigger,
at least in SQL Server,
and what the timestamp column is is
just a numeric value that is managed by SQL Server.
So as you add or update data,
this field gets updated automatically.
So here's our blog.
What EF Core does is recognizes this is a concurrency field.
Now I can set anything to be a concurrency field,
but I use the timestamp property
because it's managed by SQL Server,
so we get row-level concurrency.
What this does for us is when we do queries,
we do update statements, they change.
So for example, here when I am calling save changes,
if I didn't have a concurrency token,
what would happen is if core would say,
"Update blog set name equals bar where ID equals two."
Very simple. But the other is concurrency stamp,
what happens is that concurrency stamp
is carried with us in the queries.
So EF Core now will say,
"Update blog set name equals bar where
the ID equals two and timestamp equals 1, 2, 3, 4."
So if nobody else has changed it, the update goes through.
But if you have changed it before me,
the timestamp value might be 1,
2, 3, 4, 5.
So then it of course says, "Update the blog,
set name to bar where timestamp is 1, 2, 3,
4," and SQL Server says,
"I got nothing to do," doesn't throw an exception,
just comes back and says, "Zero records affected."
We talked a lot about the change tracker at our beginning series.
So the change tracker is tracking
how many things have changed and then it's
comparing their feedback from
SQL Server or for any database provider,
but we're talking about SQL Server specifically here.
We'll then compare the feedback from
SQL Server in our example with
the number of expected changes
and if those numbers are different in any way,
shape, or form, EF Core,
will then throw a DbUpdateConcurrencyException.
So it's a very specific exception based
on not necessary that there was a concurrency problem,
but the number of expected changes
and the number of actual changes don't match.
So here's where the power comes in.
So that makes it super easy.
Just merely by adding the timestamp column,
it'll prevent users from overriding other people's changes.
So if you do nothing else,
you have solved that problem.
But there's a lot more that you can do with EF Core.
So if we run this and we'll also look at the code,
so I've got these two blogs,
very simple, call save changes, no problem.
I'm then going to change one of
the blogs outside of EF Core world.
I could go into SQL Server Management Studio
make to change the same thing.
I then change both names.
So the change tracker says,
"There are two changes expected.
I call save changes," SQL Server says, "I changed one,
not one could be found," so then EF Core says,
"We have a mismatch, throw this DbUpdateConcurrencyException."
So let's make sure I've got the right one set
to run. We're going to run it.
I always have a rebuilt the database each time.
That's why these things take a little bit to kick off.
The way I always have a clean database when I start the examples.
>> Then again, you have to decide for your app and for
the scenario if that's a problem.
>> Well, it should always be a problem,
if somebody is overwriting data.
>> If you change the color to
green and then half an hour if
it's blue and you change it to green,
and half an hour later I change it to yellow,
and we're both allowed to change that column, no one complains.
But if you change it to green,
while I'm in the process of changing it to yellow,
is that an error or do I
just overwrite what you did and it's yellow,
which it would have been if I was five minutes later.
>> Well. So then it comes down to business decision.
But the problem is with this scenario that you just outlined
is you don't know
and I don't know that we're overwriting charged data.
>> Yes.
>> So if you're higher up on
the food chain than I'm in the organization,
you could overwrite my changes then I guess it doesn't matter,
but usually it does.
So here's the message,
database operation is expected to affect one row,
but actually affected zero rows.
Data may have been modified or deleted
since entities were reloaded.
So this is actually one of
the better messages and [inaudible]
a Microsoft product and it's actually understandable.
So there's an error message.
But the really cool part is that in the entries property
of the exception are all the ones that failed to persist.
So I can get the entity entry out
of the exception and then here are the original values.
>> Could be any of Change Tracking for checking changes,
then you're keeping track of
the original values in the current value.
So you can easily rewrite that code.
>> So here's all the original values,
so that I could go into here and pull them out.
The current value.
So that's the original values of
when I pull this from the database.
The current values would else try and change it too,
I can start using some link to say,
"Hey, which properties were modified?"
Then if I want to do that, so this all comes for free.
If I do another database call,
I can say get me all of the current database values.
So what I can now build is the screen that says I've got options.
Very simple options than just writing code.
The simple option is first one in wins,
I put a message up saying, hey,
somebody else has changed the data, reload it and try again.
I can build a screen that says,
well, first of all, I get to database values.
I check to see what I modified.
If what I modified doesn't conflict with what you modified,
then I can just silently save it.
But they never even know there was
a concurrency problem or I could build a screen that says,
"Here are the original values,
here are the current values,
here are the current database values,
select which ones you want to persist."
>> Exactly. Merge your changes in other words.
>> Yep. So we can't
just throw them back because we're still in a bad state here.
But what I can do is called reload.
So if I have found out what I want to change here what I
call reload and this was fairly recently added back into EF Core,
this says, "Discard all local changes,
get me the values in a database.
Now I can apply the result of the screen and then save it again."
So again, super powerful stuff,
very easy to implement.
Then, the basic is have a timestamp,
check your database provider if you're not using SQL Server,
it might have a little different lingo.
I can also do field level concurrency checking on like last name.
Let's say nobody can have one g pixie in the entire.
>> That's just more than enough.
>> All right then. This concludes our series.
>> Tosses out the changes that you made.
>> Right. So if you've got
a screen built that says I want to apply these,
what reload does for the most part,
you have to call a reload at some point
because you can keep trying to save this thing,
the timestamp is all right.
We saw the old timestamps.
So reload is going to get the current timestamp and then you
apply your changes to
the reloaded entity and then you can call save.
But yes, it's going to throw away your changes.
So you still have them stored up here,
there's the current values.
>> If the user has changed 12 fields and only one was at issue,
then you might want to have the ability to
reapply the changes without making them retype them, right?
>> Right. So it doesn't handle all those scenarios for you.
It gives you the power to handle
all those scenarios on your business needs.
So it's a super powerful constructed.
Again, it's one of those, for me, it's a must-do.
Always turn it on and then the business has
to figure out what you want to do when it happens.
>> It's your job to help them figure it out because there's
going to be a lot of scenarios they're
not necessarily thinking about.
>> Correct.
>> Cool. You may get a customer like me that just says,
"Tough last one in wins," and it's your job as
the developer to help
the customer see if that's really what you want.
>> Correct. Because I changed the salary,
you change the salary,
you're in after me,
you win as opposed to having a conflict.
>> Exactly. Cool.
>> Yeah. So short and sweet,
but a really powerful feature that adds a lot of business site.
>> Very good. Hope you guys enjoyed that
and we will see you next time on Visual Studio Toolbox.
>> Thanks for watching.
[MUSIC].