Tạo một Khung thực thể chung DbContext
trong một ứng dụng web là rất tệ. DbContext
lớp không an toàn theo luồng (và các lưu giữ tương tự đối với ObjectContext
của Entity Framework v1 lớp). Nó được xây dựng dựa trên khái niệm về đơn vị công việc
và điều này có nghĩa là bạn sử dụng nó để vận hành một trường hợp sử dụng duy nhất:do đó cho một giao dịch kinh doanh. Nó có nghĩa là để xử lý một yêu cầu duy nhất.
Ngoại lệ bạn nhận được xảy ra vì đối với mỗi yêu cầu, bạn tạo một giao dịch mới, nhưng hãy cố gắng sử dụng cùng một DbContext
đó . Bạn thật may mắn khi DbContext
phát hiện điều này và ném một ngoại lệ, vì bây giờ bạn phát hiện ra rằng điều này sẽ không hoạt động.
DbContext
chứa bộ đệm ẩn cục bộ của các thực thể trong cơ sở dữ liệu của bạn. Nó cho phép bạn thực hiện một loạt các thay đổi và cuối cùng gửi những thay đổi đó vào cơ sở dữ liệu. Khi sử dụng một DbContext
tĩnh duy nhất , với nhiều người dùng gọi SaveChanges
trên đối tượng đó, làm cách nào để biết chính xác điều gì nên cam kết và điều gì không nên?
Bởi vì nó không biết, nó sẽ cứu tất cả thay đổi, nhưng tại thời điểm đó, một yêu cầu khác vẫn có thể thực hiện thay đổi. Khi bạn may mắn, EF hoặc cơ sở dữ liệu của bạn sẽ không thành công, vì các thực thể ở trạng thái không hợp lệ. Nếu bạn không may mắn, các thực thể ở trạng thái không hợp lệ sẽ được lưu thành công vào cơ sở dữ liệu và bạn có thể phát hiện ra vài tuần sau đó, dữ liệu của bạn đã bị hỏng.
Giải pháp cho vấn đề của bạn là tạo ít nhất một DbContext
theo yêu cầu
. Mặc dù về lý thuyết, bạn có thể lưu vào bộ nhớ cache một ngữ cảnh đối tượng trong phiên người dùng, nhưng đây cũng là một ý tưởng tồi, vì trong trường hợp đó, DbContext
thường sẽ tồn tại quá lâu và sẽ chứa dữ liệu cũ (vì bộ nhớ cache bên trong của nó sẽ không tự động được làm mới).
Cũng lưu ý rằng có một DbContext
mỗi luồng cũng tệ như chỉ có một phiên bản duy nhất cho ứng dụng web hoàn chỉnh. ASP.NET sử dụng một nhóm luồng có nghĩa là một số lượng giới hạn các luồng sẽ được tạo ra trong suốt thời gian tồn tại của một ứng dụng web. Về cơ bản, điều này có nghĩa là DbContext
đó các phiên bản trong trường hợp đó sẽ vẫn tồn tại trong suốt thời gian tồn tại của ứng dụng, gây ra các vấn đề tương tự về tính ổn định của dữ liệu.
Bạn có thể nghĩ rằng có một DbContext
mỗi luồng thực sự an toàn cho luồng, nhưng điều này thường không xảy ra, vì ASP.NET có mô hình không đồng bộ cho phép hoàn thành các yêu cầu trên một luồng khác với nơi nó được bắt đầu (và các phiên bản mới nhất của MVC và Web API thậm chí còn cho phép số lượng chủ đề tùy ý xử lý một yêu cầu duy nhất theo thứ tự tuần tự). Điều này có nghĩa là chuỗi bắt đầu một yêu cầu và tạo ObjectContext
có thể có sẵn để xử lý một yêu cầu khác rất lâu trước khi yêu cầu ban đầu đó hoàn tất. Tuy nhiên, các đối tượng được sử dụng trong yêu cầu đó (chẳng hạn như trang web, bộ điều khiển hoặc bất kỳ lớp nghiệp vụ nào), vẫn có thể tham chiếu đến DbContext
đó . Vì yêu cầu web mới chạy trong cùng một chuỗi đó, nó sẽ nhận được cùng một DbContext
ví dụ như những gì yêu cầu cũ đang sử dụng. Điều này một lần nữa gây ra các điều kiện chủng tộc trong ứng dụng của bạn và gây ra các vấn đề an toàn luồng tương tự như một DbContext
toàn cầu nguyên nhân trường hợp.