你的位置:首页 > ASP.net教程

[ASP.net教程]EF中的开放式并发(EF基础系列)


好久没更新EF这个系列了,现在又重新开始。

这次学习,开放式并发。首先拿出数据库脚本:

说明一下,这个数据库脚本是之前的章节中稍作修改的:

USE [SchoolDB]GO/****** Object: Table [dbo].[Student]  Script Date: 11/30/2015 21:42:07 ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [dbo].[Student](  [StudentID] [INT] NOT NULL,  [StudentName] [NVARCHAR](100) NULL,  [StandardID] [INT] NULL,  [RowVersion] [TIMESTAMP] NOT NULL, CONSTRAINT [PK__Student__32C52A7903317E3D] PRIMARY KEY CLUSTERED (  [StudentID] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]GOALTER TABLE [dbo].[Student] WITH CHECK ADD CONSTRAINT [FK__Student__Standar__0519C6AF] FOREIGN KEY([StandardID])REFERENCES [dbo].[Standard] ([StandardID])GOALTER TABLE [dbo].[Student] CHECK CONSTRAINT [FK__Student__Standar__0519C6AF]GO

然后,我们在数据模型中更新一下模型EDMx

 

 

可以看到Student模型上面,出现了Rowversion字段,我们选中它,右键-->属性,修改并发模式为Fixed。

EF will now include a RowVersion column in the where clause, whenever you do an update operation and if the rowversion value is different than in the where clause then it will throwDbUpdateConcurrencyExection.

下面开始实践:

using System;using System.Collections.Generic;using System.Data.Entity;using System.Data.Entity.Core.Objects;using System.Data.Entity.Infrastructure;using System.Linq;using System.Text;using System.Threading.Tasks;namespace EFTutorials{  class Program  {    static void Main(string[] args)    {      Student stu1 = null;      Student stu2 = null;      using (var db = new SchoolDBEntities1())      {        db.Configuration.ProxyCreationEnabled = false;         stu1 = db.Students.Where(s => s.StudentID == 1).FirstOrDefault();      }      using (var db = new SchoolDBEntities1())      {        db.Configuration.ProxyCreationEnabled = false;        stu2 = db.Students.Where(s => s.StudentID == 1).FirstOrDefault();      }      stu1.StudentName = "Edit Stuent1";      stu2.StudentName = "Edit Stuent2";      using (var db = new SchoolDBEntities1())      {        try        {          db.Entry(stu1).State = EntityState.Modified;          db.SaveChanges();        }        catch (DbUpdateConcurrencyException ex)        {          Console.WriteLine("Optimistic Concurrency exception occured");        }              }      using (var db = new SchoolDBEntities1())      {        try        {          db.Entry(stu2).State = EntityState.Modified;          db.SaveChanges();        }        catch (DbUpdateConcurrencyException ex)        {          Console.WriteLine("Optimistic Concurrency exception occured");        }              }    }  }}


执行完stu1那个查询之后:

SELECT TOP (1)
[Extent1].[StudentID] AS [StudentID],
[Extent1].[StudentName] AS [StudentName],
[Extent1].[StandardID] AS [StandardID],
[Extent1].[RowVersion] AS [RowVersion]
FROM [dbo].[Student] AS [Extent1]
WHERE 1 = [Extent1].[StudentID]

执行完,stu1的保存修改之后:

exec sp_executesql N'UPDATE [dbo].[Student]
SET [StudentName] = @0, [StandardID] = NULL
WHERE (([StudentID] = @1) AND ([RowVersion] = @2))
SELECT [RowVersion]
FROM [dbo].[Student]
WHERE @@ROWCOUNT > 0 AND [StudentID] = @1',N'@0 nvarchar(100),@1 int,@2 binary(8)',@0=N'Edit Stuent1',@1=1,@2=0x00000000000007D6

可以肯定的得出,在这里会出错,也就是并发。

Concurrency in Code-First:

You can create a timestamp property in code-first by usng [Timestamp] attribute. Make sure that the property type is byte[] because timestamp is binary in C#.

      [Timestamp]    public byte[] RowVersion { get; set; }    

EF includes a property in the where clause, during the update operation, if the property is marked with the Timestamp attribute.

You can resolve concurrency exceptions many ways. Visit msdn for detailed information on how to resolve optimistic concurrency.

Download sample project for the basic tutorials.

 

 

今天有点晚了,明天来继续,怎么解决这个并发。哈哈!!