 On today's Visual Studio Toolbox, Phil's 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? Hi, welcome to Visual Studio Toolbox. I'm your host, Robert Green, and joining me today is Phil Jepixi. Hello, Phil. Hey, Robert. We are now in part, let me check my notes, six of our Entity Framework Core in-depth series, and today we're going to talk about concurrency. Correct. Concurrency is a common problem with software, and it's, 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. Whether editing in the same fields or 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. Right. Concurrency, we've dealt with this for years, and the problem is how do you know when it happens, and then the business decision is what do you do when it does happen? Right. 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. From the business standpoint, they might not understand 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, right? So there's a row-level concurrency and it's 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, and so it's not something that we'll fight so hard against now, as I did in the past. Yeah. So should we jump in and see how easy it is to concurrency checking in EF Core? Let's do that. All right. So let me share my screen here. All right. 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, and 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. Mm-hmm. 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 EF Core would say, update blog set name equals bar where ID equals 2. Very simple. But now there's a 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 ID equals 2 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. Right. So then EF Core 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. Right. We talked a lot about the change tracker in our beginning series. So the change tracker is tracking how many things have changed and then is comparing the 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 DB update concurrency exception. So it's a very specific exception based on not necessarily that there was a concurrency problem, but the number of expected changes and the number of actual changes don't match. Right. Right. So here's where the power comes in. So that makes it super easy, right? 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 let's look at the code, right? 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. Right, I can go into SQL Server Management Studio and make the change, 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. The other one couldn't be found. Right. So then EF Core says, oh, we have a mismatch. Throw this DB update concurrency exception. So let's make sure I've got the right one set to run. We're going to run it. I always have a rebuild database each time. That's why these things take a little bit to kick off. That way I always have a clean database when I start the examples. And 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's overwriting data. That's why it's- Well, 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, okay, so then it comes down to a 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 each other's data. Yes. Right? So if you're higher up on the food chain than I am in the organization, you can overwrite my changes and I guess it doesn't matter, but usually it does. So here's the message, database operation expected to affect one row but actually affected zero rows. Data may have been modified or deleted since entities were loaded. So this is actually one of the better messages of a Microsoft product, right? It's actually understandable. Look at that. So there's our message, but the really cool part is that in the entries property of the exception are all the ones that failed to persist. Right. So I can get the entity entry out of the exception and then here are the original values. It's the beauty of change tracking. If you're checking changes, then you're keeping track of the original values and the current values. So you can easily write that code. So here's all the original values that I could go into here and pull them out. Mm-hmm. The current values, so that's the original values of when I pulled this from the database. The current values what I was trying to change it to, I can start using some link to say, hey, which properties were modified? Mm-hmm. And then if I wanna do another, 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 a screen that says, I've got options, very simple options. And then it's 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. Right. I can build a screen that says, well, first of all, I get the database values. I check to see what I modified. And if what I modified doesn't conflict with what you modified, then I can just silently save it. They never even know there was a concurrency problem. Right. 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. Now merge your changes, in other words. Yep. So we can't just throw them back because we're still in bad state here. But what I can do is call reload. And so if I have found out what I want to change here, when I call reload, and this was fairly recently added back into EF Core, this says, all right, discard all the local changes, get me the values from the database. Now I can apply the result of the screen and then save it again. So again, super powerful stuff. Very easy to implement. And 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, you can only have one Gepixi in the entire system. That's more than enough. All righty then. And this concludes our series. It tosses out the changes that you made. Correct? Correct? 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 isn't right. Right. We still have the old timestamp. So reload is gonna get the current timestamp. And then you apply your changes to the reloaded entity and then you can call save. But yes, it's gonna throw away your changes so you would have had to, I mean, you still have them stored up here, right? Yep. There's the current values. Okay. Okay, so you may, if the users 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 construct that I just, again, it's one of those, for me, it's a must do, right? Always turn it on. And then the business has to figure out what you wanna do when it happens. Right. And it's your job to help them figure it out because there's gonna be a lot of scenarios they're not necessarily thinking about. Correct. All right, cool. And 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 change the salary, you change the salary, you're in after me, you win, as opposed to having a conflict. Exactly. All right, cool. Yep, so short and sweet, but a really powerful feature that adds a lot of business hype. Very good. All right, hope you guys enjoyed that. And we will see you next time on Visual Studio Toolbox. Thanks for watching. Let's do this.