Tôi đang xây dựng một hệ thống xử lý hàng loạt. Các lô Units
có số lượng từ 20-1000. Mỗi Unit
về bản chất là một hệ thống phân cấp của các mô hình (một mô hình chính và nhiều mô hình con). Nhiệm vụ của tôi liên quan đến việc lưu từng hệ thống phân cấp mô hình vào cơ sở dữ liệu dưới dạng một giao dịch đơn lẻ (hoặc mỗi hệ thống phân cấp cam kết hoặc phân cấp lại). Thật không may EF
không thể xử lý hai phần của hệ thống phân cấp mô hình do tiềm năng chứa hàng nghìn bản ghi.EF Competing SaveChanges() Gọi
Những gì tôi đã thực hiện để giải quyết vấn đề này được thiết lập SqlBulkCopy
để xử lý hai mô hình có khả năng cao này và để EF
xử lý phần còn lại của phần chèn (và tính toàn vẹn tham chiếu).
hàng loạt Loop:
foreach (var unitDetails in BatchUnits)
{
var unitOfWork = new Unit(unitDetails);
Task.Factory.StartNew(() =>
{
unitOfWork.ProcessX(); // data preparation
unitOfWork.ProcessY(); // data preparation
unitOfWork.PersistCase();
});
}
Đơn vị:
class Unit
{
public PersistCase()
{
using (var dbContext = new CustomDbContext())
{
// Need an explicit transaction so that
// EF + SqlBulkCopy act as a single block
using (var scope = new TransactionScope(TransactionScopeOption.Required,
new TransactionOptions() {
IsolationLevel = System.Transaction.IsolationLevel.ReadCommitted
}))
{
// Let EF Insert most of the records
// Note Insert is all it is doing, no update or delete
dbContext.Units.Add(thisUnit);
dbContext.SaveChanges(); // deadlocks, DbConcurrencyExceptions here
// Copy Auto Inc Generated Id (set by EF) to DataTables
// for referential integrity of SqlBulkCopy inserts
CopyGeneratedId(thisUnit.AutoIncrementedId, dataTables);
// Execute SqlBulkCopy for potentially numerous model #1
SqlBulkCopy bulkCopy1 = new SqlBulkCopy(...);
...
bulkCopy1.WriteToServer(dataTables["#1"]);
// Execute SqlBulkCopy for potentially number model #2
SqlBulkCopy bulkCopy2 = new SqlBulkCopy(...);
...
bulkCopy2.WriteToServer(dataTables["#2"]);
// Commit transaction
scope.Complete();
}
}
}
}
Ngay bây giờ tôi đang chủ yếu bị mắc kẹt giữa một tảng đá và một nơi khó khăn. Nếu tôi rời khỏi số IsolationLevel
được đặt thành ReadCommitted
, tôi sẽ nhận được các sự tắc nghẽn giữa các câu hỏi EF
INSERT
khác nhau Tasks
.
Nếu tôi đặt IsolationLevel
thành ReadUncommitted
(điều mà tôi nghĩ là không sao vì tôi không làm bất kỳ SELECTs
), tôi nhận được DbConcurrencyExceptions
.
Tôi không thể tìm thấy bất kỳ thông tin nào tốt về DbConcurrencyExceptions
và Entity Framework
nhưng tôi đoán rằng ReadUncommitted
về cơ bản sẽ gây ra EF
để nhận thông tin "hàng được chèn" không hợp lệ.
CẬP NHẬT
Dưới đây là một số thông tin cơ bản về những gì đang thực sự gây ra tôi deadlocking vấn đề trong khi làm chèn:
Rõ ràng vấn đề này cùng có mặt một vài năm trước, khi LINQ to SQL xuất hiện và Microsoft đã sửa nó bằng cách thay đổi cách scope_identity() được chọn. Bạn không chắc chắn lý do tại sao vị trí của họ đã thay đổi này là một vấn đề SQL Server khi cùng một vấn đề đến với Entity Framework.
_competing_ hoặc _completing_? –