Mặc định Entity Framework hỗ trợ Optimistic Concurrency. Trong optimistic concurrency EF lưu thực thể vào CSDL, giả định rằng dữ liệu tương tự không thay đổi từ lúc thực thể được tải.  Nếu nó xác định rằng dữ liệu đã thay đổi sau đó một exception được đưa ra và bạn phải loại bỏ xung đột trước khi thử lưu nó lại lần nữa.

Chúng ta hãy xem làm thế nào để kiểm soát optimistic concurrency với thực thể Student.

Đầu tiên bạn cần có một cột rowversion trong bảng Student để kiểm soát concurrency với thực thể Student. Rowversion là một kiểu dữ liệu trong SQL Server tự động khởi tạo sốnhị phân duy nhất bất cứ khi nào thao tác insert hoặc update được thực hiện trong một bảng. Kiểu dữ liệu rowversion đơn giản là một số tự tăng. Rowversion tương tự kiểu dữ liệu timestamp.

Tạo một cột mới RowVersion trong bảng Student với kiểu dữ liệu timestamp như trình bày bên dưới:

Entity Framework 5.0 Tutorial

Note: Giá trị của RowVersion sẽ được thêm và cập nhật tự động bởi CSDL trong khi thao tác Insert và Update.

Giờ tạo một Entity Data Model như trình bày trong phần Tạo Entity Data Model hoặc nếu bạn đã có một EDM thì cập nhật nó bằng cách click chuột phải vào phần thiết kế-> Update Model From Database -> Refresh Student table. Và bạn sẽ nhìn thấy thuộc tính RowVersion được thêm vào thực thể Student.

Sau đó bạn cần cài đặt concurrency mode để sửa đổi bằng cách click chuột phải trên thuộc tính RowVersion trong thực thể Student (click chuột phải vào thuộc tính RowVersion chứ không phải thực thể Student) -> select Property. Đổi Concurrency Mode thành Fixed từ None trong cửa sổ thuộc tính như bên dưới:

Entity Framework 5.0 Tutorial

EF giờ sẽ chèn một cột RowVersion trong mệnh đề where bất cứ khi nào bạn thực hiện một thao tác update và nếu giá trị rowversion là khác biệt hơn trong mệnh đề where thì nó sẽ ném ra DbUpdateConcurrencyException.

Đoạn mã sau chỉ ra rằng User1 và User2 lấy vềcùng một sinh viên và update StudentName ở cùng một thời điểm:

Student student1WithUser1 = null; 
Student student1WithUser2 = null;

//User 1 gets student
using (var context = new SchoolDBEntities())
{
    context.Configuration.ProxyCreationEnabled = false;
    student1WithUser1 = context.Students.Where(s => s.StudentID == 1).Single();
}
//User 2 also get the same student
using (var context = new SchoolDBEntities())
{
    context.Configuration.ProxyCreationEnabled = false;
    student1WithUser2 = context.Students.Where(s => s.StudentID == 1).Single();
}
//User 1 updates Student name
student1WithUser1.StudentName = "Edited from user1";

//User 2 updates Student name
student1WithUser2.StudentName = "Edited from user2";

User1 lưu thay đổi trước User2. Vì vậy khi User2 cố lưu những thay đổi sẽ nhận về một concurrency exception:

//User 1 saves changes first
using (var context = new SchoolDBEntities())
{
    try
    {
        context.Entry(student1WithUser1).State = EntityState.Modified;
        context.SaveChanges();
    }
    catch (DbUpdateConcurrencyException ex)
    {
        Console.WriteLine("Optimistic Concurrency exception occured");
    }
}

//User 2 saves changes after User 1. 
//User 2 will get concurrency exection 
//because CreateOrModifiedDate is different in the database 
using (var context = new SchoolDBEntities())
{
    try
    {
        context.Entry(student1WithUser2).State = EntityState.Modified;
        context.SaveChanges();
    }
    catch (DbUpdateConcurrencyException ex)
    {
        Console.WriteLine("Optimistic Concurrency exception occured");
    }
}

Concurrency trong Code-First:

Bạn có thể tạo một đặc tính timestamp trong Code-First bằng cách sử dụng thuộc tính [Timestamp]. Chắc chắn rằng kiểu đặc tính là byte[] bởi vì timestamp là nhị phân trong C#.

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

EF chèn một đặc tính trong mệnh đề where trong khi thao tác update, nếu đặc tính được đánh dấu với thuộc tính Timestamp

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

Nguồn: http://www.entityframeworktutorial.net/

Advertisements