Data Annotation Feature-ConcurrencyCheck feature [Code-First series], concurrency
The ConcurrencyCheck feature can be applied to the attributes of the domain class. When EF executes the update operation, Code-First places the column value in the where Condition Statement. You can use this CurrencyCheck feature to perform concurrent checks using existing columns, instead of using a separate TimeStamp column for concurrent checks.
See the following code:
using System;using System.Collections.Generic;using System.ComponentModel.DataAnnotations;using System.ComponentModel.DataAnnotations.Schema;using System.Linq;using System.Text;using System.Threading.Tasks;namespace EF2{ [Table("StudentInfo")] public class Student { [Key] [Column(Order=1)] public int StudentKey1 { get; set; } [Key] [Column(Order=2)] public int StudentKey2 { get; set; } [Column("Name",TypeName="ntext")] [MaxLength(20)] [ConcurrencyCheck] public string StudentName { get; set; } [NotMapped()] public int? Age { get; set; } public int StdId { get; set; } [ForeignKey("StdId")] public virtual Standard Standard { get; set; } 1449391525 public byte[] RowVersion { get; set; } }}
Then let's modify the Main function testing code:
using System;using System.Collections.Generic;using System.Data.Entity;using System.Data.Entity.Infrastructure;using System.Linq;using System.Text;using System.Threading.Tasks;namespace EF2{ class Program { static void Main(string[] args) { Student stuModel1 = null; Student stuModel2 = null; using (var db = new DbContextClass()) { stuModel1 = db.Students.Where(s => s.StudentKey1 == 1 && s.StudentKey2 == 1).Single(); } using (var db = new DbContextClass()) { stuModel2 = db.Students.Where(s => s.StudentKey1 == 1 && s.StudentKey2 == 1).Single(); } stuModel1.StudentName = "Test Only For one"; stuModel2.StudentName = "Test Only For twos"; try { using (var db = new DbContextClass()) { db.Entry(stuModel1).State = EntityState.Modified; db.SaveChanges(); } } catch (DbUpdateConcurrencyException ex) { Console.WriteLine(ex.Message); } try { using (var db = new DbContextClass()) { db.Entry(stuModel2).State = EntityState.Modified; db.SaveChanges(); } } catch (DbUpdateConcurrencyException ex) { Console.WriteLine(ex.Message); } Console.ReadKey(); } }}
Then the error is sent and the message is:
exec sp_executesql N'UPDATE [dbo].[StudentInfo]SET [StudentName] = @0, [StdId] = @1WHERE ((([StudentKey1] = @2) AND ([StudentKey2] = @3)) AND ([StudentName] = @4))',N'@0 nvarchar(20),@1 int,@2 int,@3 int,@4 nvarchar(20)',@0=N'Test Only For one',@1=1,@2=1,@3=1,@4=N'Test Only For one'
Note:
Note that TimeStamp attribute can only be applied to a single byte array property in a class, whereas ConcurrencyCheck attribute can be applied to any number of properties with any ype.
The TimeStamp feature can only be used in a single-byte attribute class, but the ConcurrencyCheck feature can be used in any quantity or type of attributes.