2014-05-21 35 views
10

Mam dość standardową aplikację MVC 5 składającą się z warstwy repozytorium, warstwy usługi i warstwy kontrolera. Aby zachować oddzielenie i testowanie każdej warstwy, używam programu Ninject do wstrzykiwania zależności.ASP.NET MVC 5 Zarządzanie kontekstem asynchronicznym

Aby odświeżyć nowe umiejętności, zdecydowałem się użyć nowych akcji kontrolera zadań z asynchronizacją/oczekiwaniem na operacje związane z IO dla usług i metod kontrolera.

Normalnie po prostu skorzystać z InRequestScope wiązania jak tak

kernel.Bind<IDbContext>().To<BlogContext>().InRequestScope(); 

W ogóle to działa dobrze teraz, jednak jeśli wybrałem debugować mojej aplikacji, lub połączyć kilka gąsienicowa Entity Framework obiektów razem i zapisać, Stwierdzam, że kontekst został usunięty lub pojawiają się problemy z śledzeniem. Rozumiem, dlaczego tak się dzieje, jest to całkowicie logiczne, ponieważ operacja nie ma już miejsca w wątku IIS, więc w jaki sposób Ninject wie, że powinien używać tego samego kontekstu.

Aby obejść ten problem, mogę przekazać kontekst do każdego wywołania repozytorium z poziomu mojej warstwy usługi lub nawet z poziomu kontrolera, jeśli zajdzie taka potrzeba. Jednak czuję, że wygląda to niechlujnie i wolałbym, aby Ninject zarządzał kontekstem tego obiektu, jeśli to możliwe.

Jakie są najlepsze strategie radzenia sobie z tym w elegancki/minimalistyczny sposób, zachowując mój kod podobny do przykładów podanych poniżej?

Oto przykład jednego z moich metod kontroler

public virtual async Task<ActionResult> Edit(int id) 
    { 
     var editViewModel = await BuildDefaultCreateEditViewModel(); 

     var post = await postService.GetNonDeletedPost(id); 
     ... 
     ... 
     return View(MVC.Admin.Post.Views.CreateEdit, editViewModel); 
    } 

metody usługi

public async Task<PostDTO> GetNonDeletedPost(int postId) 
    { 
     return (await PostRepostiory.GetPost(postId)).ConvertToDTO(); 
    } 

metoda Repository

public Task<Post> GetPost(int postId) 
    { 
     return QueryableExtensions.SingleOrDefaultAsync(
       DbSet.Where(post => post.PostId == postId) 
       .Include(post => post.PostVersions) 
       .Include(post => post.Categories) 
       .Include(post => post.Files)); 
    } 
+1

Używasz DbContextFactory? I mają tendencję do używania 'TransientScope' zamiast Życzenie, a ja nigdy nie mam żadnych problemów –

+0

skutecznie nadzieję, że mogę używać Ninject w sposób podobny do DbContextFactory podobny do korzystania InRequestScope. Gdybym miał zejść trasę korzystania z DBContextFacotry problem jaki mam wiedzieć, które zwracają się do asynchronicznej wątek należy do wciąż widoczne, jak mogę negować tego? chodzi o zakres korzystania przejściowy, który stworzy nowy kontekst za repozytorium, które jest dobre dla usług, które korzystają z jednego, ale kiedy używam kilka (wzór elewacji) szwy obiektów razem i oszczędność nie będzie działać jako obiekty z różnych repozytoriów będzie pod różne śledzone konteksty. – jps

+0

Tak, jak używam ninject, z DbContextFactory, pozwala mi wstrzyknąć kontekst do repozytorium wszystkie w TransientScope. :) –

Odpowiedz

1

W swoim stanowisku oraz w powiązanych komentarze istnieją pewne świetne przykłady tego, jak to zrobić.

Jednak dla niektórych innych czytelników, którzy mogliby się tu natknąć, chciałbym rzucić szczere pytanie: Czy naprawdę potrzebujesz asynchronicznych kontrolerów?

Asynchroniczne działania kontrolera zwalniają liczbę wątków potrzebnych do obsługi żądań; Jeśli jednak nie zabraknie ci nici i nie będziesz w stanie tego zrobić, tworzysz złożoność, próbując rozwiązać problem, którego nie masz ani nie spodziewasz się mieć. Lub: "Czy Async jest naprawdę darmowy i zawsze lepszy?"

Skutecznie, staram się pokazać, że jednym bardzo realnym rozwiązaniem (a może nie tym, którego szukasz) byłoby po prostu nie używać kontrolerów asynchronicznych - jeśli w rzeczywistości nie jest to potrzebne (co zależałoby od twojego konkretnego okoliczności.)

To dobre, stare, zwariowane rozwiązanie rozwiązania problemu poprzez usunięcie problemu. W szczególności proponuję to, ponieważ usunięcie złożoności wydaje się być jednym z celów.

Jak wybrać, którego użyć? jest dłuższa lista, ale dwie z najlepszych pytania są:

  • Czy Twoje pozycje krótkie bieganie?
  • A jeśli nie, to są Twoje pozycje CPU związany?

http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4

Z powyższego linku „Korzystanie asynchronicznych metod działania w zakresie działalności związanej z procesorem zapewnia żadnych korzyści i uzyskania bardziej nad głową.”

Powiązane problemy