Bất kỳ nhà phát triển nào cũng đã từng gặp khó khăn khi giải quyết các vấn đề liên quan đến truy cập dữ liệu đồng thời. Truy cập dữ liệu đồng thời (concurrency) xảy ra nếu có nhiều hơn một người dùng đang chỉnh sửa cùng một dữ liệu tại cùng một thời điểm.
Mặc định Entity Framework hỗ trợ xử lý truy cập dữ liệu đồng thời (concurrency). Entity Framework sẽ lưu một thông tin phiên bản vào cơ sở dữ liệu, thông tin này sẽ tự động thay đổi mỗi khi bạn thực hiện lệnh update
.
Khi Entity Framework thực hiện lệnh update
nó sẽ bổ sung thêm thông tin phiên bản vào mệnh đề where
của truy vấn. Nếu dữ liệu đã được thay đổi trước đó thì sẽ có một ngoại lệ xảy ra.
Ví dụ sau đây sẽ minh họa cách xử lý truy cập dữ liệu đồng thời bằng cách thêm một cột VersionNo vào bảng Course.
Đi đến trình thiết kế và nhấp chuột phải vào cửa sổ trình thiết kế và chọn Update Model from Database…
Bạn sẽ thấy cột VersionNo đã được thêm vào trong thực thể Course.
Nhấp chuột phải vào cột VersionNo mới được tạo và chọn Properties rồi thay đổi ConcurrencyMode
thành Fixed
như trong hình dưới đây.
Sau khi đã thiết lập ConcurrencyMode của VersionNo thành Fixed, bất cứ khi nào Course được cập nhật, lệnh update
sẽ tìm Course bằng cách sử dụng thuộc tính EntityKey và thuộc tính VersionNo.
Hãy xem xét một kịch bản đơn giản sau:
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
namespace DatabaseFirstDemo
{
class Program
{
static void Main(string[] args)
{
Course c1 = null;
Course c2 = null;
//User 1 gets Course
using (var context = new UniContextEntities())
{
context.Configuration.ProxyCreationEnabled = false;
c1 = context.Courses.Where(s ⇒ s.CourseID == 1).FirstOrDefault();
}
//User 2 also get the same Course
using (var context = new UniContextEntities())
{
context.Configuration.ProxyCreationEnabled = false;
c2 = context.Courses.Where(s ⇒ s.CourseID == 1).FirstOrDefault();
}
//User 1 updates Course Title
c1.Title = "Edited from user1";
//User 2 updates Course Title
c2.Title = "Edited from user2";
//User 1 saves changes first
using (var context = new UniContextEntities())
{
try
{
context.Entry(c1).State = EntityState.Modified;
context.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
Console.WriteLine("User1: Optimistic Concurrency exception occurred");
}
}
//User 2 saves changes after User 1.
//User 2 will get concurrency exection
//because CreateOrModifiedDate is different in the database
using (var context = new UniContextEntities())
{
try
{
context.Entry(c2).State = EntityState.Modified;
context.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
Console.WriteLine("User2: Optimistic Concurrency exception occurred");
}
}
}
}
}
Bạn có thể sử dụng TimestampAttribute cho thuộc tính VersionNo trong Code-First. Hãy đảm bảo rằng kiểu dữ liệu của VersionNo là kiểu byte[]
.
[Timestamp]
public byte[] VersionNo { get; set; }
EF sẽ tự động thêm VersionNo vào trong mệnh đề where
trong khi thực hiện thao tác update
.
Bạn có thể vui lòng tắt trình chặn quảng cáo ❤️ để hỗ trợ chúng tôi duy trì hoạt động của trang web.
2 kịch bản lưu dữ liệu trong Entity Framework Core là kịch bản được kết nối và kịch bản ngắt kết nối.
Tạo ứng dụng .NET Core Console đầu tiên và cấu hình sử dụng Entity Framework Core.
Truy vấn trong Entity Framework Core có gì mới? Truy vấn trong EF Core khác EF ở những điểm nào.
Entity Framework Core toàn tập sẽ hướng dẫn bạn tất cả mọi thứ về Entity Framework Core.