Recentemente ho apportato modifiche alla mia Applicazione MVC3 nel tentativo di smaltire correttamente gli oggetti DbContext
[1]. Questo ha funzionato molto in fase di sviluppo, ma una volta che l'applicazione è stata trasferita al mio server di produzione, ho iniziato a intermittenza ottenendo alcune eccezioni divertenti che si sarebbero protratte fino a quando l'AppPool non fosse stato riciclato. Le eccezioni si possono far risalire al codice nel mio personalizzato AuthorizeAttribute
e assomigliano:Problemi dopo lo smaltimento DbContext
System.InvalidOperationException: The 'Username' property on 'User' could not be set to a 'Int32' value. You must set this property to a non-null value of type 'String'.
System.InvalidOperationException: The 'Code' property on 'Right' could not be set to a 'String' value. You must set this property to a non-null value of type 'Int32'.
(schema di database simile a questa: gli utenti: [Guid, String, ...], i diritti: [Guid, Int32,. ..])
È come se alcuni "fili sono stati incrociati" e l'applicazione sta mescolando i risultati del database: cercando di materializzare il risultato Right
come User
e viceversa.
Per gestire lo smaltimento di DbContext
, ho inserito il codice per archiviarlo a livello di controller. Quando il controller viene smaltito, dispongo anche lo DbContext
. So che è hacky, ma lo AuthorizeAttribute
utilizza lo stesso contesto tramite filterContext.Controller
.
C'è qualcosa di sbagliato nella gestione del ciclo di vita dell'oggetto di DbContext
in questo maniero? Ci sono spiegazioni logiche sul motivo per cui sto ricevendo le eccezioni incrociate sopra?
[1] Anche se capisco che non è necessario smaltire gli oggetti DbContext
, di recente mi sono imbattuto in diverse fonti che affermavano che si trattava della migliore pratica a prescindere.
Edit (per @ commento di MikeSW)
Una proprietà del AuthorizeAttribute
che rappresenta il DbContext
è stato impostato nel metodo OnAuthorization
, quando il AuthorizationContext
è portata. Successivamente, questa proprietà viene utilizzata nel metodo AuthorizeCore
.
Puoi condividere parte del codice pertinente della vostra abitudine AuthorizeAttribute? Si noti che un attributo viene utilizzato come singleton da asp.net mvc. Inoltre stai usando un contenitore DI? – MikeSW
@MikeSW Ho aggiunto informazioni sull'utilizzo sopra riportato. Non sto usando un contenitore DI. Con le informazioni fornite sopra, sembrerebbe che questi errori si verifichino a causa della concorrenza: nel tempo che intercorre tra "OnAuthorization" e "AuthorizeCore", un'altra richiesta attiva "OnAuthorization" e clobbers la proprietà 'DbContext'. Questo segue? –
Sì, questo è il tuo problema. [Autorizza] è fondamentalmente un singleton e stai modificando la proprietà dbcontext con ogni richiesta. Io suggerisco di usare un DI Container, registrarsi DbContext con tempo di vita HttpPerInstance quindi utilizzare DependencyResolver.Current.GetService() in OnAuthorization metodo. Il contenitore deve gestire anche lo smaltimento di DbContext –
MikeSW