📅  最后修改于: 2020-11-21 07:19:39             🧑  作者: Mango
任何数据访问开发人员在回答有关数据并发的问题时都会遇到困难,“如果一个以上的人同时编辑同一数据会发生什么?”
我们当中最幸运的人处理的业务规则是:“没问题,最后一个获胜。”
在这种情况下,并发不是问题。更有可能的是,它不是那样简单,并且没有解决所有情况的灵丹妙药。
默认情况下,实体框架将采用“获胜的最后一个”的路径,这意味着即使有人在检索时间数据和保存时间数据之间更新了数据,也将应用最新更新。
让我们举个例子来更好地理解它。下面的示例在“课程”表中添加新列VersionNo。
转到设计器,然后在设计器窗口上单击鼠标右键,然后从数据库中选择更新模型…
您将看到课程实体中添加了另一列。
右键单击新创建的列VersionNo,然后选择Properties,然后将ConcurrencyMode更改为Fixed,如下图所示。
将Course.VersionNo的ConcurrencyMode设置为Fixed时,无论何时更新课程,Update命令都将使用其EntityKey和VersionNo属性查找课程。
让我们看一个简单的场景。两个用户同时检索同一门课程,用户1将该课程的标题更改为Maths并在用户2之前保存更改。后来,当用户2更改在用户1保存其更改之前检索的该课程的标题时,情况下,用户2将获得并发异常“ User2:发生了乐观并发异常” 。
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
namespace DatabaseFirstDemo {
class Program {
static void Main(string[] args) {
Course c1 = null;
Course c2 = null;
//User 1 gets Course
using (var context = new UniContextEntities()) {
context.Configuration.ProxyCreationEnabled = false;
c1 = context.Courses.Where(s ⇒ s.CourseID == 1).Single();
}
//User 2 also get the same Course
using (var context = new UniContextEntities()) {
context.Configuration.ProxyCreationEnabled = false;
c2 = context.Courses.Where(s ⇒ s.CourseID == 1).Single();
}
//User 1 updates Course Title
c1.Title = "Edited from user1";
//User 2 updates Course Title
c2.Title = "Edited from user2";
//User 1 saves changes first
using (var context = new UniContextEntities()) {
try {
context.Entry(c1).State = EntityState.Modified;
context.SaveChanges();
} catch (DbUpdateConcurrencyException ex) {
Console.WriteLine("User1: Optimistic Concurrency exception occurred");
}
}
//User 2 saves changes after User 1.
//User 2 will get concurrency exection
//because CreateOrModifiedDate is different in the database
using (var context = new UniContextEntities()) {
try {
context.Entry(c2).State = EntityState.Modified;
context.SaveChanges();
} catch (DbUpdateConcurrencyException ex) {
Console.WriteLine("User2: Optimistic Concurrency exception occurred");
}
}
}
}
}