HTML5技术

Entity Framework Code First实现乐观并发 - 东城慕水

字号+ 作者:H5之家 来源:H5之家 2017-10-12 11:00 我要评论( )

Entity Framework Code First实现乐观并发 不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址 本博文翻译自: https://www.codeproject.com/Articles/817432/Optimistic-Concurrency-in-E

Entity Framework Code First实现乐观并发

不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址

本博文翻译自:
https://www.codeproject.com/Articles/817432/Optimistic-Concurrency-in-Entity-Framework-Code-Fi

介绍

本文描述了使用Entity Framework Code First处理乐观并发性的不同配置

并发性

在计算机科学中,并发性是系统的一个属性,在这个系统中,多个计算同时执行,并且有可能相互影响。

在web应用程序中,这是一个多用户环境,在保存数据库中的数据时,可能存在并发性。并发性大致分为两种类型:1)悲观并发2)乐观并发

1) 悲观并发

数据库中的悲观并发包括锁行,以防止其他用户以影响当前用户的方式修改数据。

在这种方法中,用户执行一个操作,其中一个锁被应用,其他用户不能在该记录上执行相同的操作,直到该锁被释放。

2) 乐观并发

相比之下,在乐观并发中,当用户阅读时,行不会被锁定。当用户试图更新这一行时,系统必须确定该记录是否被另一个用户修改过,因为它被读取了。

开始编写代码

让我们创建一个控制台应用程序来探索处理乐观并发的不同情况。

步骤

下表显示了用于乐观并发的不同配置。

配置乐观并发

Convention None

Data Annotation [Timestamp]

Fluent API .IsRowVersion()

1) Convention

Entity Framework Code First 没有任何处理乐观并发的约定。您可以使用Data Annotation或Fluent API来处理乐观并发。

2) Data Annotation

Code First使用[Timestamp] 处理乐观并发性的属性。

a) 修改 EducationContext.cs 文件如下:

using System.Data.Entity; namespace ConcurrencyCheck.Models { class EducationContext : DbContext { public EducationContext() : base("EducationContext") { } public DbSet<Student> Students { get; set; } } }

在base("EducationContext")中通过Code First 指令在 App.config 文件中使用名为"EducationContext"的连接字符串

b) 修改 Student.cs 文件如下:

using System.ComponentModel.DataAnnotations; namespace ConcurrencyCheck.Models { public class Student { public int StudentId { get; set; } public string RollNumber { get; set; } public string FirstName { get; set; } public string LastName { get; set; } [Timestamp] public byte[] RowVersion { get; set; } } }

请注意,在 Student 类中有一个属性 RowVersion ,它是 byte[] 类型,并被分配使用 [Timestamp] 属性来处理乐观的并发性。

c) 将 App.config 文件中的连接字符串更改为指向一个有效的数据库:

<connectionStrings> <add name="EducationContext" providerName="System.Data.SqlClient" connectionString="Server=DUKHABANDHU-PC; Database=ConcurrencyCheck;Integrated Security=SSPI" /> </connectionStrings>

在这里,我们将数据库名称作为ConcurrencyCheck,它将在应用程序运行时通过 Code First 创建。

d) 修改 Program.cs 文件在每次应用程序运行时都要删除和创建数据库:

static void Main(string[] args) { Database.SetInitializer(new DropCreateDatabaseAlways<EducationContext>()); using (var context = new EducationContext()) { context.Students.Add(new Student { FirstName = "Dukhabandhu", LastName = "Sahoo", RollNumber = "1" }); context.SaveChanges(); } Console.WriteLine("Database Created!!!"); Console.ReadKey(); }

如果运行该应用程序,代码首先将创建数据库 ConcurrenCheck 它拥有两个表 MigrationHistory 和 Students 。

如果您看到 Students 表中的 RowVersion 列(在SQL Sever中),它的数据类型是 timestamp 。

RowVersion 和 TimeStamp 是不同数据库提供程序用于相同目的的两个术语。当创建或更新 Students 表中的记录时,数据库将自动更新 RowVersion 值到新值。即使您为 rowversion 列发送值,数据库(SQL Server)也不使用该值来进行插入或更新操作。

当添加到 Students 表的新记录时生成的SQL:

exec sp_executesql N'INSERT [dbo].[Students]([RollNumber], [FirstName], [LastName]) VALUES (@0, @1, @2) SELECT [StudentId], [RowVersion] FROM [dbo].[Students] WHERE @@ROWCOUNT > 0 AND [StudentId] = scope_identity()',N'@0 nvarchar(max) ,@1 nvarchar(max) ,@2 nvarchar(max) ',@0=N'1',@1=N'Dukhabandhu',@2=N'Sahoo'

您可以看到查询不仅插入了一个新记录,而且还返回了 RowVersion 的值。

当进行更新和删除操作时,会发生实际的并发检查。在更新和删除 Students 表的记录时,请参阅下面如何发生并发检查。

UPDATE SQL exec sp_executesql N'UPDATE [dbo].[Students] SET [RollNumber] = @0 WHERE (([StudentId] = @1) AND ([RowVersion] = @2)) SELECT [RowVersion] FROM [dbo].[Students] WHERE @@ROWCOUNT > 0 AND [StudentId] = @1',N'@0 nvarchar(max) ,@1 int,@2 binary(8)',@0=N'2',@1=1,@2=0x00000000000007D1

我们看到 WHERE 条件,在更新记录时,它比较了 studentid (主键)和 RowVersion 。

DELETE SQL exec sp_executesql N'DELETE [dbo].[Students] WHERE (([StudentId] = @0) AND ([RowVersion] = @1))',N'@0 int,@1 binary(8)',@0=1,@1=0x00000000000007D1

在删除记录代码之前,先创建一个查询来比较标识符(主键 StudentId )和行版本( RowVersion 字段)用于乐观并发。

3) Fluent API

Fluent API使用 IsRowVersion() 方法来配置乐观并发。

为了测试Fluent API的配置,从 Students 类的 RowVersion 属性中删除 [Timestamp] 属性,并在 EducationContext 类中覆盖 ** onmodel()** 方法:

protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Student>().Property(s => s.RowVersion).IsRowVersion(); base.OnModelCreating(modelBuilder); } 配置非时间戳字段

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • Entity Framework Core Like 查询揭秘 - Sweet-Tang

    Entity Framework Core Like 查询揭秘 - Sweet-Tang

    2017-09-13 12:05

  • 负载均衡基础知识 - coderbinbin

    负载均衡基础知识 - coderbinbin

    2017-09-01 15:05

  • 自动化的基于TypeScript的HTML5游戏开发 - wildfirecode

    自动化的基于TypeScript的HTML5游戏开发 - wildfirecode

    2017-08-30 16:01

  • Entity Framework Core 2.0 新特性 - 晓晨Master

    Entity Framework Core 2.0 新特性 - 晓晨Master

    2017-08-16 17:01

网友点评
=