12

Trong môi trường MVC/WebAPI, tôi sẽ sử dụng InRequestScope để liên kết DbContext.Ninject - Trong phạm vi nào DbContext sẽ bị ràng buộc khi RequestScope là vô nghĩa?

Tuy nhiên, bây giờ tôi đang ở trên ứng dụng Console/Dịch vụ Windows/vai trò công nhân Azure (không thực sự quan trọng, chỉ không có phạm vi yêu cầu web), định kỳ tạo một số Tasks chạy không đồng bộ. Tôi muốn mỗi công việc có DbContext riêng của mình và vì các nhiệm vụ chạy trên chủ đề của riêng mình, tôi đã thử ràng buộc DbContext bằng cách sử dụng InThreadScope.

Thật không may, tôi nhận ra rằng DbContext không được xử lý khi công việc được hoàn thành. Điều thực sự xảy ra là, luồng trả về Thread Pool và khi nó được gán một nhiệm vụ mới, nó đã có một DbContext, vì vậy DbContexts vẫn tồn tại mãi mãi.

Có cách nào InThreadScope có thể được sử dụng tại đây hoặc tôi nên sử dụng một số phạm vi khác không? Làm thế nào có thể ThreadScope được sử dụng khi các chủ đề đang trở về từ ThreadPool mỗi bây giờ và sau đó?

+0

Bạn nhận thấy rằng [mỗi Chủ đề Lối sống được coi là có hại] (https://stackoverflow.com/questions/14591422/why-is-perthreadlifetimemanager-used-in-this-example). – Steven

+0

@Steven Vâng, tôi hiểu rồi. Vậy làm cách nào để triển khai phạm vi tùy chỉnh (hoặc giải pháp khác)? –

+1

Bạn không nên sử dụng phạm vi nào cả. Sử dụng một nhà máy để tạo DbContext (mà về cơ bản là một đơn vị * công việc *) - và truyền nó xung quanh khi cần thiết. Nếu phần mềm vẫn đơn giản như bạn mô tả nó, bạn cũng có thể sử dụng một phạm vi được đặt tên (được định nghĩa bởi Task và kết buộc DbContext 'InNamedScope'). Nhưng đó không phải là bằng chứng trong tương lai ví dụ khi bạn muốn tạo DbContext bên ngoài một tác vụ hoặc khi bạn muốn có nhiều (tuần tự) DbContext bên trong một tác vụ, ... vv – BatteryBackupUnit

Trả lời

1

Nếu bạn quyết định đi với phạm vi tùy chỉnh, giải pháp là:

public sealed class CurrentScope : INotifyWhenDisposed 
{ 
    [ThreadStatic] 
    private static CurrentScope currentScope; 

    private CurrentScope() 
    { 
    } 

    public static CurrentScope Instance => currentScope ?? (currentScope = new CurrentScope()); 

    public bool IsDisposed { get; private set; } 

    public event EventHandler Disposed; 

    public void Dispose() 
    { 
     this.IsDisposed = true; 
     currentScope = null; 
     if (this.Disposed != null) 
     { 
      this.Disposed(this, EventArgs.Empty); 
     } 
    } 
} 

Binding:

Bind<DbContext>().To<MyDbContext>().InScope(c => CurrentScope.Instance) 

Và cuối cùng:

using (CurrentScope.Instance) 
{ 
    // your request... 
    // you'll get always the same DbContext inside of this using block 
    // DbContext will be disposed after going out of scope of this using block 
} 
Các vấn đề liên quan