博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Entity Framework 乐观并发处理
阅读量:6237 次
发布时间:2019-06-22

本文共 3848 字,大约阅读时间需要 12 分钟。

Entity Framework 乐观并发处理

      有一段时间没有更新博客了,今天终于有一些时间,和大家讨论一个Entity Framework 乐观并发处理的问题。首先需要说明的是,这里提到的 “并发” 并不是指的多线程处理,也就是笔者这里要讨论的是另外一个问题场景,这个场景描述如下:

  1. 系统用户A从数据库中取得一条记录Record-1

  2. 系统用户B从数据库中取得同一条记录Record-1

  3. 系统用户B修改记录Record-1,并保存到数据库

  4. 系统用户A修改记录Record-1,并保存到数据库

  这个场景里面的问题是系统用户B对数据路记录Record-1的修改被A的修改冲掉了,这种行为在某些业务场景中是正确的,但是在某些场景中可能会有问题,因为这样的场景中A可能希望感知Record-1的变化,并做出相应的代码策略处理。针对这种场景Entity Framework 专门有一种解决方案,Timestamp或者叫Rowersion,具体实现代码如下, 在需要支持乐观并发的model上增加Timestamp字段,字段的名字叫RowVersion,当然对应的数据库表上也要加上这个字段RowVersion,类型是timestamp, 这样在以上描述的场景发生时,系统就会捕获到相应的异常,从而有机会对这种场景进行相应的业务处理。

 

如果不喜欢Data Annotation,也可以使用 Fluent api 进行标记,具体代码如下,

 

modelBuilder.Entity
().Property(p => p.RowVersion).IsRowVersion();

 

namespace ContosoUniversity.Models{    public class Department    {
[ConcurrencyCheck] public int DepartmentID { get; set; } [StringLength(50, MinimumLength = 3)] public string Name { get; set; } [DataType(DataType.Currency)] [Column(TypeName = "money")] public decimal Budget { get; set; } [DataType(DataType.Date)] [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] [Display(Name = "Start Date")] public DateTime StartDate { get; set; } public int? InstructorID { get; set; } [Timestamp] public byte[] RowVersion { get; set; } public virtual Instructor Administrator { get; set; } public virtual ICollection
Courses { get; set; } }}

 

try    {          db.Entry(departmentToUpdate).OriginalValues["RowVersion"] = rowVersion;          await db.SaveChangesAsync();          return RedirectToAction("Index");   }   catch (DbUpdateConcurrencyException ex)   {          var entry = ex.Entries.Single();          var clientValues = (Department)entry.Entity;          var databaseEntry = entry.GetDatabaseValues();          if (databaseEntry == null)          {              ModelState.AddModelError(string.Empty, "Unable to save changes. The department was deleted by another user.");          }          else          {              var databaseValues = (Department)databaseEntry.ToObject();              if (databaseValues.Name != clientValues.Name)              ModelState.AddModelError("Name", "Current value: "               + databaseValues.Name);               if (databaseValues.Budget != clientValues.Budget)               ModelState.AddModelError("Budget", "Current value: "               + String.Format("{0:c}", databaseValues.Budget));               if (databaseValues.StartDate != clientValues.StartDate)                ModelState.AddModelError("StartDate", "Current value: "               + String.Format("{0:d}", databaseValues.StartDate));               if (databaseValues.InstructorID != clientValues.InstructorID)               ModelState.AddModelError("InstructorID", "Current value: "                + db.Instructors.Find(databaseValues.InstructorID).FullName);               ModelState.AddModelError(string.Empty, "The record you attempted to edit "                            + "was modified by another user after you got the original value. The "                            + "edit operation was canceled and the current values in the database "                            + "have been displayed. If you still want to edit this record, click "                            + "the Save button again. Otherwise click the Back to List hyperlink.");               departmentToUpdate.RowVersion = databaseValues.RowVersion;              }    }

 

当然Timestamp字段不是必须单独添加的,也可以使用model上的已有字段,假设这个字段是DepartmentID,我们可以使用ConcurrencyCheck注解进行标记,当然也可是使用Fluent api 进行标记,具体代码如下,

modelBuilder.Entity
().Property(p => p.DepartmentID).IsConcurrencyToken();

 

总结

本文详细描述了一种Entity Framework 乐观并发处理的解决方案,并且通过Data Annotation和Fluent api 两种方式进行了详细的说明,希望对大家有所帮助。

转载地址:http://ujzia.baihongyu.com/

你可能感兴趣的文章
Drools 文档(KIE概述)
查看>>
Python进程专题2:multiprocessing创建进程
查看>>
聊聊rocketmq的NettyEncoder及NettyDecoder
查看>>
从0开始用python写一个命令行小游戏(三)
查看>>
ubuntu-desktop安装
查看>>
学会这15点,让你分分钟拿下 Redis 数据库
查看>>
再读Generator和Co源码
查看>>
「案例」让房东在 Airbnb 上展示他们的热情好客
查看>>
vue-cli的项目结构
查看>>
利用 WeakMap 对 Vue 新建数组中的对象赋予 :key
查看>>
CSS3中display属性的Flex布局-圣杯布局实例
查看>>
Javascript 基本概念(操作符)
查看>>
在阿里云Kubernetes容器服务上打造TensorFlow实验室
查看>>
外观模式(Facade)
查看>>
《程序员的自我修养》读书笔记——静态链接
查看>>
数据科学指南
查看>>
让多个元素贴边平分布局
查看>>
基于ZXing Android实现生成二维码图片和相机扫描二维码图片即时解码的功能
查看>>
单点手势库简单思考实现
查看>>
浏览器内核、JS 引擎、页面呈现原理及其优化
查看>>