8

Tôi có một dự án MVC3 sử dụng Ninject, Entity Framework và mẫu Đơn vị công việc với một lớp Dịch vụ.Vấn đề phạm vi Ninject với Công việc/Chủ đề

Lớp AsyncService của tôi có chức năng bắt đầu tác vụ nền, làm ví dụ, thêm người dùng vào kho lưu trữ Người dùng. Vấn đề hiện tại của tôi là nhiệm vụ chỉ chạy một cách chính xác trong vài giây trước khi tôi nhận được lỗi mà DbContext đã được xử lý. Ngữ cảnh cơ sở dữ liệu của tôi, được tiêm với InRequestScope của Ninject() dường như bị xử lý, vì InRequestScope() liên kết nó với HttpContext.

Tôi đã đọc về InThreadScope(), tuy nhiên tôi không biết cách triển khai đúng cách trong dự án MVC của mình.

Câu hỏi của tôi là: Cách chính xác để sử dụng Ninject trong Nhiệm vụ của tôi là gì?

public class AsyncService 
{ 
    private CancellationTokenSource cancellationTokenSource; 
    private IUnitOfWork _uow; 
    public AsyncService(IUnitOfWork uow) 
    { 
     _uow = uow; 
    } 
    public void AsyncStartActivity(Activity activity) 
    { 
    ...snip... 
     this.cancellationTokenSource = new CancellationTokenSource(); 
     var cancellationToken = this.cancellationTokenSource.Token; 
     var task = Task.Factory.StartNew(() => 
      { 
       foreach (var user in activity.UserList) 
       { 
        this._uow.UserRepository.Add(new User() {UserID = user}); 
       } 
       this._uow.Save(); 
      }, cancellationToken); 
    ...snip... 
    } 
} 

Trả lời

5

InRequestScope 'd đối tượng là Dispose d ở phần cuối của một yêu cầu vì vậy nó không thể được sử dụng trong trường hợp này. InThreadScope cũng không phù hợp vì sẽ sử dụng lại UoW cho một số tác vụ.

Việc bạn có thể làm là khai báo AsyncService làm đối tượng phạm vi cho tất cả các đối tượng trong sử dụng phần mở rộng NamedScope.

Xem http://www.planetgeek.ch/2010/12/08/how-to-use-the-additional-ninject-scopes-of-namedscope/

+3

Có một mẫu mã? Jason, nơi bạn có thể làm cho nó hoạt động? Tôi đang gặp vấn đề tương tự và theo liên kết không giúp được gì. –

+0

Tôi có cùng một vấn đề này, tôi rất muốn xem một số mã mẫu cho kịch bản này. –

0

Đây là một giải pháp lộn xộn mà tôi đã sử dụng trong quá khứ bằng cách sử dụng các plugin ChildKernel (Tôi nghĩ rằng phạm vi được đặt tên sẽ sạch hơn nhiều). Về cơ bản tôi tạo ra một hạt nhân con, và phạm vi tất cả mọi thứ liên quan đến UoW như singleton trong hạt nhân con. Sau đó tôi tạo một kernel con mới cho mỗi Task, xử lý UoW, và commit hoặc rollback.

IAsyncTask là một giao diện với 1 phương pháp, Execute()

private Task void ExecuteTask<T>() where T:IAsyncTask 
{ 

     var task = Task.Factory.StartNew(() => 
              { 
      var taskKernel = _kernel.Get<ChildKernel>(); 
      var uow = taskKernel.Get<IUnitOfWork>(); 
      var asyncTask = taskKernel.Get<T>(); 

      try 
      { 
       uow.Begin(); 
       asyncTask.Execute(); 
       uow.Commit(); 
      } 
      catch (Exception ex) 
      { 
       uow.Rollback(); 
       //log it, whatever else you want to do 
      } 
      finally 
      { 
       uow.Dispose(); 
       taskKernel.Dispose(); 
      } 
     }); 
     return task; 
} 
Các vấn đề liên quan