2012-06-08 11 views
5

Sono di fronte a un problema con il contesto di oggetto EF4 che memorizzo all'interno di HttpContext.Current.Items e quindi desidero disporre non appena la richiesta viene gestita completamente.contesto oggetto di eliminazione su application_endrequest

Su evento Aplication_EndRequest chiamo il metodo Terminate() della RepositoryContext, che troverebbe l'attiva ObjectContext dalla collezione HttpContext.Current.Items, e chiamare Close() sulla sua connessione e Dispose() su di esso.

Il problema è che a volte ho un comportamento strano su una delle mie pagine. In alcune occasioni ho un errore che dice:

L'istanza ObjectContext è stato eliminato e non può più essere utilizzata per le operazioni che richiedono una connessione

ho pensato che forse questo potrebbe accadere in quanto non solo pagina le richieste chiamano l'evento Application_EndRequest una volta che finiscono ma anche le richieste di immagine ed ecc ', e quindi forse a volte altre richieste eliminano l'ObjectContext della richiesta della pagina principale prima di completare il suo lavoro, ma ciò non dovrebbe accadere poiché tutto è fatto sulla collezione HttpContext .Current.Items che non è ovviamente condiviso tra le richieste HTTP .

Inoltre, a causa della ricerca, potrebbe essere causato dal caricamento lento di alcune richieste di database, ma questo non dovrebbe essere il caso qui perché non chiamo Dispose in nessun altro codice (ho controllato) e quindi Dispose() sul EndRequest dovrebbe essere chiamato solo quando è terminato tutto,, non dovrebbe?

Qualche idea su cosa potrebbe causare questo? Come posso testarlo? che cosa suggeriresti?

Grazie!

+0

Che aspetto ha la traccia dello stack quando si riceve questo errore? – AakashM

+0

Puoi pubblicare il codice della tua classe RepositoryContext? –

+0

ecco la traccia: http://img850.imageshack.us/img850/3210/erroryourate.jpg sembra che sia perché nel mezzo dell'operazione il contesto dell'oggetto viene eliminato. Ma ancora non capisco come possa accadere, se dispongo solo di Application_EndRequest. – Sagi

risposta

1

Ciò significa che Dispose() è già stato chiamato su ObjectContext. Ci sono molte diverse ragioni per spiegare perché questo sta accadendo, ma si riduce al fatto che qualcosa sta chiamando Dispose() prima di Application_EndRequest. Senza tutta la fonte sarebbe impossibile dire esattamente il perché.

Poiché si stanno chiedendo consigli, il mio primo sarebbe quello di rimuovere ObjectContext da HttpContext. La connessione al database dovrebbe vivere solo per un breve periodo ed eseguire un'attività specifica. Se è di breve durata, puoi inserire ObjectContext all'interno di un'istruzione using che chiamerà automaticamente Dispose().

+0

Penso che il tempo di una richiesta sia ok. Questo pattern è ereditato da NHibernate e si chiama open-session-in-view. Funziona bene. – ivowiblo

+0

Non c'è nulla che si interrompa facendo open-in-view senza mettere ObjectContext in HttpContext. ViewModel saprebbe come eseguire le azioni per colpire il database nel momento in cui viene eseguito il rendering della vista. Avere un contesto per richiesta significa anche che non è intuitivo ciò che SaveChanges() dovrebbe effettivamente eseguire, poiché l'intera vita delle richieste dovrebbe essere rivista. –

+0

Bene, ho controllato e controllato e non ho mai smesso da nessun'altra parte, ho cercato tutti "usando" e tutti "disponiamo" sul codice sorgente su tutte le soluzioni, e niente. Per ora, sto solo facendo objectContext.Connection.Close() invece di dispose e sembra funzionare bene. BTW, questo accade solo sulle proprietà di navigazione e non altro. – Sagi

1

Supponiamo di avere una classe che fornisce la corrente ObjectContext, è possibile un programmatore, a seguito di alcuni esempi di un blog o qualcosa del genere, aveva scritto questo:

using(var context = ContextProvider.GetCurrentContext()){ 
    ... 
} 

e disposto l'ObjectContext prima della richiesta finisce.

Se si desidera verificare dove l'ObjectContext è in via di dismissione, si può fare questo:

Nell'implementazione ObjectContext, cambiare il metodo Dispose per:

public override void Dispose() { 
    throw new InvalidOpearationException("Gotcha!"); 
} 

public void ActuallyDisposePlease() { 
    base.Dispose(); 
} 

E nel Application_EndRequest chiamare l'ActuallyDisposePlease() metodo.

DI CORSO, questo è per il test/debug/diagnosi prospettiva e MAI dovrebbe colpire la produzione.

Problemi correlati