Entity Framework 乐观并发处理

小说:中顺麻将赢话费作者:董公帝戏更新时间:2019-03-23字数:99717

Entity Framework 乐观并发处理


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<Department>().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<Course> 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<Person>().Property(p => p.DepartmentID).IsConcurrencyToken();

 

总结

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

当前文章:http://0477auto.com/play/11gzdd8sw7.html

发布时间:2019-03-23 00:55:11

js游戏代码大全 斗地主单机版不用网络 三个老k手机版下载 凸透镜成像规律 四川熊猫麻将外卦神器 就玩台州麻将手机版 道友请留步 手机棋牌捕鱼游戏下载 乙末豪客传奇全部歌曲 51pk游戏下载

编辑:公道通

我要说两句: (0人参与)

发布