EF 6 - Concurrency
Concurrency trong Entity Framework
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:
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:
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.
Ví dụ sau minh họa việc xử lý ngoại lệ đồng thời:
Student student = null;
using (var context = new SchoolDBEntities())
{
student = context.Students.First();
}
//Edit student name
Console.Write("Enter New Student Name:");
student.StudentName = Console.ReadLine(); //Assigns student name from console
using (var context = new SchoolDBEntities())
{
try
{
context.Entry(student).State = EntityState.Modified;
context.SaveChanges();
Console.WriteLine("Student saved successfully.");
}
catch (DbUpdateConcurrencyException ex)
{
Console.WriteLine("Concurrency Exception Occurred.");
}
}
Giả sử rằng có hai người dùng thực thi đoạn mã trên. User1 và User2 đều có cùng một thực thể Student. Bây giờ, Người dùng1 nhập tên sinh viên mới và lưu tên đó trước User2. Vì vậy, User1 sẽ nhận được thông báo "Sinh viên đã lưu thành công" trong khi User2 sẽ nhận được "Đã xảy ra ngoại lệ đồng thời.".