Tôi đã có một ứng dụng API sử dụng nhiều phân đoạn cơ sở dữ liệu, với StructureMap để tiêm phụ thuộc. Một trong các tiêu đề bắt buộc trong mỗi lệnh gọi API là ShardKey
, cho tôi biết cơ sở dữ liệu nào cuộc gọi này đang giải quyết. Để thực hiện điều này, tôi có một lớp OwinMiddleware
gọi ShardingMiddleware
, trong đó có chứa đoạn mã sau (snipped cho rõ ràng):Xung đột chéo chuỗi trong StructureMap
var nestedContainer = container.GetNestedContainer();
using (var db = MyDbContext.ForShard(shardKey)) // creates a new MyDbContext with connection string appropriate to shardKey
{
nestedContainer.Configure(cfg => cfg.For<MyDbContext>().Use(db));
await Next.Invoke(context);
}
này làm việc tuyệt vời trong môi trường thử nghiệm của tôi và vượt qua một loạt các xét nghiệm hội nhập.
Nhưng kiểm tra tích hợp có hiệu quả đơn luồng. Khi tôi triển khai điều này vào môi trường QA, nơi một ứng dụng thực đang truy cập API của tôi với nhiều cuộc gọi đồng thời, mọi thứ bắt đầu đi hình quả lê. Ferinstance:
System.ObjectDisposedException: Không thể truy cập đối tượng được xử lý. Một nguyên nhân phổ biến của lỗi này là xử lý một ngữ cảnh đã được giải quyết từ việc tiêm phụ thuộc và sau đó cố gắng sử dụng cùng một cá thể ngữ cảnh ở nơi khác trong ứng dụng của bạn. Điều này có thể xảy ra là bạn đang gọi Dispose() trên ngữ cảnh, hoặc gói ngữ cảnh trong một câu lệnh sử dụng. Nếu bạn đang sử dụng tiêm phụ thuộc, bạn nên để thùng chứa phụ thuộc tiêm xử lý các trường hợp bối cảnh.
Hoặc các trường hợp ngoại lệ khác cho thấy rằng Sơ đồ cấu trúc không có phiên bản hợp lệ MyDbContext
khả dụng.
Với tôi có vẻ như nhiều chủ đề bằng cách nào đó làm rối loạn cấu hình của nhau, nhưng với cuộc sống của tôi, tôi không thể hiểu được, nhìn như tôi đang sử dụng một thùng chứa lồng nhau để lưu trữ bối cảnh cơ sở dữ liệu cho mỗi API gọi điện.
Bất kỳ ý tưởng nào có thể xảy ra ở đây?
Cập nhật: Tôi cũng đã thử trừu tượng ngữ cảnh Db của mình thành giao diện. Không có sự khác biệt thực sự; Tôi vẫn gặp lỗi
System.InvalidOperationException: Đã xảy ra lỗi khi cố gắng tạo bộ điều khiển kiểu 'SomeController'. Đảm bảo rằng bộ điều khiển có một hàm tạo công khai không tham số. ---> StructureMap.StructureMapConfigurationException: Không Instance mặc định đã được đăng ký và không thể tự động xác định cho loại 'MyNamespace.IMyDbContext'
Cập nhật 2: tôi đã giải quyết được vấn đề, nhưng tiền thưởng vẫn còn mở. Xin vui lòng xem câu trả lời của tôi dưới đây.
'DbContext' của bạn có thể được giữ nguyên dưới dạng [Phụ thuộc Captive] (http://blog.ploeh.dk/2014/06/02/captive-dependency/). Hãy chắc chắn rằng người tiêu dùng của sự phụ thuộc này không có một đời lâu hơn của 'DbContext' hoặc-tốt hơn-ngăn chặn tiêm DbContext vào người tiêu dùng trực tiếp. Một 'DbContext' là dữ liệu thời gian chạy và dữ liệu thời gian chạy [không nên được đưa vào các thành phần] (https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=99). Thay vào đó hãy ẩn DbContext đằng sau một trừu tượng. – Steven