2010-04-27 27 views
13

sto imparando EF ora e hanno una domanda per quanto riguarda l'ObjectContext:Entity Framework ObjectContext riutilizzo

Devo creare un'istanza di ObjectContext per ogni query (funzione), quando ho accedere al database?

Oppure è meglio crearlo una volta (singleton) e riutilizzarlo?

Prima EF stavo usando Enterprise Library blocchi l'accesso ai dati e ha creato un'istanza di dataacess per la funzione DataAccess ...

+0

IMO - uso DI per risolvere l'istanza del contesto oggetto EF e giocare con le vite di verificare quale opzione si dà i risultati migliori ... – Sunny

risposta

14

Sicuramente per ogni query. È un oggetto leggero quindi non ci sono molti costi sostenuti per crearne uno ogni volta che ne hai bisogno.

Inoltre, più a lungo mantieni un oggetto ObjectContext attivo, più oggetti memorizzati nella cache saranno contenuti durante l'esecuzione di query su di esso. Ciò potrebbe causare problemi di memoria. Pertanto, avere ObjectContext come un singleton è un'idea particolarmente negativa. Man mano che la tua applicazione viene utilizzata, carichi sempre più entità nel singleton ObjectContext fino a quando non hai in memoria l'intero database (a meno che non separi le entità quando non ne hai più bisogno).

E poi c'è un problema di manutenibilità. Un giorno provi a rintracciare un errore ma non riesci a capire dove sono stati caricati i dati che l'hanno causato.

+3

ero d'accordo con questa risposta se le uniche scelte erano singleton e in accesso. Ma c'è un intero spettro di vite, alcune delle quali potrebbero fornire prestazioni migliori a seconda dell'applicazione. Il contesto memorizza le cache per una ragione :) Per-richiesta è la "più sicura" del gruppo accanto all'accesso. –

1

Non utilizzare un singleton .. chiunque utilizzi la tua app lo condividerà e ogni sorta di cose pazzesche accadrà quando il contesto dell'oggetto traccerà le entità.

vorrei aggiungere che come membro privato

+0

Intendo singleton per sessione (ogni utente ne ha il proprio) e ho intenzione di disabilitare il tracking – verror

+0

Sono d'accordo con la prima risposta di rwwilden. –

15

Penso che il modo più comune è quello di usarlo per ogni richiesta. Crealo all'inizio, fai quello che ti serve (il più delle volte sono operazioni che richiedono ObjectContext comuni), disponi alla fine. La maggior parte dei framework DI supporta questo scenario, ma è possibile utilizzare anche HttpModule per creare il contesto e posizionarlo in HttpContext.Current.Items. Questo è un semplice esempio:

public class MyEntitiesHttpModule : IHttpModule 
{ 
    public void Init(HttpApplication application) 
    { 
     application.BeginRequest += ApplicationBeginRequest; 
     application.EndRequest += ApplicationEndRequest; 
    } 

    private void ApplicationEndRequest(object sender, EventArgs e) 
    { 
     if (HttpContext.Current.Items[@"MyEntities"] != null) 
      ((MyEntities)HttpContext.Current.Items[@"MyEntities"]).Dispose(); 
    } 

    private static void ApplicationBeginRequest(Object source, EventArgs e) 
    { 
     var context = new MyEntities(); 
     HttpContext.Current.Items[@"MyEntities"] = context; 
    } 
} 
+1

Penso che questa sia una soluzione meno gestibile rispetto alla semplice creazione di un ObjectContext quando ne hai bisogno nel livello dati. La mia obiezione contro questa soluzione è che crei una dipendenza tra il tuo livello di interfaccia utente e il tuo livello dati che non è necessario. Il modo in cui comunichi con un database è una preoccupazione interna per il livello dati. In secondo luogo, all'inizio potrebbe sembrare semplice non dover mai preoccuparsi dei problemi di caricamento lento, ma un giorno si sta cercando di rintracciare un bug e non è possibile determinare dove è andato male perché non si ha idea di dove i dati che hanno causato il bug è stato caricato (parlando per esperienza ..) –

+1

@rwwilden: Ci dispiace, ma come si crea dipendenza tra interfaccia utente e livello dati? Sto usando un modello di repository e gli archivi devono condividere il contesto. Il contesto è iniettato dal contenitore DI. La richiesta non è così lunga e non ha così tante operazioni che possono causare così tanti problemi. Se usi schemi appropriati, non avrai problemi. – LukLed

+1

@rwwilden: c'erano milioni di domande sulla riutilizzazione di ObjectContext, qui su SO e altre pagine. L'utilizzo per richiesta sembra dominare, non è solo la mia opinione. – LukLed

1

Come Luke dice che questa domanda è stata posta numerose volte su SO.

Per un'applicazione Web, il ciclo di richiesta sembra funzionare meglio. Singleton è decisamente una cattiva idea.

Per richiesta funziona bene perché una pagina Web ha un utente, forse alcuni progetti appartenenti a quell'utente, forse alcuni messaggi per quell'utente. Vuoi lo stesso ObjectContext in modo che tu possa andare a User.Messages per ottenerli, magari contrassegnare alcuni messaggi come letti, magari aggiungere un Progetto e poi commettere o abbandonare l'intero grafico dell'oggetto al completamento del ciclo di pagine.

+1

Singleton statico non è solo una cattiva idea, è anche non thread safe! Un contesto creato dovrebbe essere usato solo in un thread. –

0

Post in ritardo qui da 7 mesi. Attualmente sto affrontando questa domanda nella mia app e mi sto appoggiando alla soluzione @LukLed creando un ObjectContext singleton per la durata della mia HttpRequest. Per la mia architettura, ho diversi controlli che vanno nella costruzione di una pagina e questi controlli hanno tutti i loro problemi di dati che estraggono i dati di sola lettura dallo strato EF. Sembra uno spreco per loro creare e utilizzare i propri ObjectContext. Inoltre, ci sono alcune situazioni in cui un controllo può inserire dati nel contesto che potrebbero essere riutilizzati da altri controlli. Ad esempio, nella mia pagina principale, la mia intestazione nella parte superiore della pagina contiene informazioni utente che possono essere riutilizzate dagli altri controlli sulla pagina.

La mia unica preoccupazione è che possa richiamare entità nel contesto che influirà sulle query di altri controlli. Non l'ho ancora visto, ma non so se sto chiedendo dei guai. Immagino che vedremo!

0
public class DBModel { 

     private const string _PREFIX = "ObjectContext"; 

     // DBModel.GetInstance<EntityObject>(); 
     public static ObjectContext GetInstance<T>() { 
      var key = CreateKey<T>(); 
      HttpContext.Current.Items[key] = HttpContext.Current.Items[key] ?? Activator.CreateInstance<T>(); 
      return HttpContext.Current.Items[key] as ObjectContext; 
     } 

     private static string CreateKey<T>() { 
      return string.Format("{0}_{1}", _PREFIX, typeof(T).Name); 
     } 
    } 
Problemi correlati