5

Ho un problema piuttosto complicato. Sto utilizzando FluentValidation.MVC nel mio progetto ASP.NET MVC 5. In esso, utilizzo un pattern di repository per verificare se l'indirizzo email di un utente non è duplicato. Il problema non è in realtà il modello di repository; è che il repository utilizza un contesto di Entity Framework iniettato nel costruttore in fase di esecuzione:Iniettore semplice "L'operazione non può essere completata perché DbContext è stato eliminato" durante la convalida MVC

public class SomeRepository 
{ 
    //IEFContext is something I modified the T4 template to generate 
    public SomeRepository(IEFContext context) 
    { 
    _context = context; 
    } 
} 

L'applicazione utilizza questo approccio e funziona grande. SimpleInjector collega il mio contesto EF, che ha lo scopo di utilizzare la richiesta web Per ASP.NET (avvolge HttpContext.Items).

Dim httpLifecycle = New SimpleInjector.Integration.Web.WebRequestLifestyle(True) 
container.Register(of IEFContext, EFContext)(httpLifecycle) 

Nessun problema con l'app qui, solo la convalida. Quando il server riceve l'operazione di post, l'errore che sto ottenendo è "L'operazione non può essere completata perché DbContext è stato eliminato". Sembra che non possa utilizzare alcun codice relativo all'EF in un attributo FluentValidation, che utilizza un contesto EF su una base di richiesta web. Niente di speciale l'attributo di convalida, che fa:

public class Val : AbstractValidator<Entity> 
{ 
    public Val() 
    { 
     _repos = Container.GetInstance<ISomeRepos>(); 
     RuleFor(i => i.Email).Must((o, v) => 
     { 
      _repos.HasDistinctEmail(o.ID, v); 
     } 
    } 
} 

Il contesto sarebbe dovuto morire con la richiesta precedente in quanto memorizzato nel HttpContext.Items. Qualche idea su cosa sta succedendo? So che impostando True su WebRequestLifecycle, sto causando la disposizione del contesto EF alla fine della richiesta. Penserei che sarebbe desiderabile.

risposta

4

mia scommessa migliore è che un'istanza della classe Val viene memorizzato nella cache per la durata del AppDomain (singleton), il che significa che il suo costruttore viene chiamato solo una volta e quindi si risolve solo una singola ISomeRepos, causando che repo essere promosso anche a singleton (e con esso, tutte le sue dipendenze).

La soluzione rapida è semplice, spostare la chiamata GetInstance all'interno del delegato:

public Val() 
{ 
    RuleFor(i => i.Email).Must((o, v) => 
    { 
     repos = Container.GetInstance<ISomeRepos>(); 
     repos.HasDistinctEmail(o.ID, v); 
    } 
} 
+0

che è stato! Grazie. –