Sì, la durata predefinita per DbContext
è con ambito. Questo è inteso in questo modo.
L'istante di istanza DbContext
è piuttosto economico e si assicura che il proprio non usi molte risorse. Se si dispone di un valore DbContext
con una durata singleton, tutti i record letti una volta verranno tracciati dallo DbContext
, a meno che non si disabiliti specificamente il tracciamento. Ciò richiederà molto più utilizzo della memoria e continuerà a crescere.
E più i brani sono DbContext
, minore sarà la prestazione. Questo è il motivo per cui spesso vedi DbContext
utilizzato solo all'interno di un blocco using(var context = new AppDbContext())
.
Nelle applicazioni Web, tuttavia, l'utilizzo del blocco using
non è corretto, poiché la durata è gestita dallo framework e, se lo si smaltisce, le chiamate successive non avranno esito positivo con un'eccezione.
Se si utilizza la durata transitoria sull'altro lato, si perderà la funzionalità "transazione". Con scope, lo DbContext
ha un ambito di transazione lungo quanto la richiesta.
Se è necessario un controllo più dettagliato, è necessario utilizzare il modello Unità di lavoro (che è già utilizzato da DbContext
).
riguarda la seconda domanda:
Se si crea un servizio, deve avere una vita che è uguale a quella del campo di applicazione o meno lungo (leggi: con mirino o transitorio).
Se si richiede esplicitamente una durata maggiore per un servizio, è necessario immettere un servizio di fabbrica o un metodo di fabbrica DbContext
nel servizio.
È possibile raggiungere questo obiettivo con qualcosa di simile
services.AddTransient<Func<AppDbContext>>((provider) => new Func<MyDbContext>(() => new AppDbContext()));
services.AddSingleton<IMySingletonService, MySingletonService>();
E il servizio potrebbe essere simile a questa:
public class MySingletonService : IMySingletonService, IDisposable
{
private readonly AppDbContext context;
public MySingletonService(Func<AppDbContext> contextFactory)
{
if(contextFactory == null)
throw new ArgumentNullException(nameof(contextFactory));
// it creates an transient factory, make sure to dispose it in `Dispose()` method.
// Since it's member of the MySingletonService, it's lifetime
// is effectively bound to it.
context = contextFactory();
}
}
in una web app è davvero il controller che gestisce tutta la vita? o è la DI che dispone di scopi nell'ambito di una richiesta alla fine della richiesta? Mi piacerebbe capire che meglio –
Il mio male. Intendevo dire quadro. Esiste una factory di controller ('IControllerFactory', vedere https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.Core/Controllers/DefaultControllerFactory.cs per l'implementazione predefinita) in' CreateController 'metodo che crea il controller e lo dispone e lo dispone e le sue dipendenze nel metodo' ReleaseController() '. Vedi anche questo problema su GitHub per maggiori dettagli sul funzionamento interno e perché funziona in questo modo: https://github.com/aspnet/Mvc/issues/3727 – Tseng
grazie. se ho un repository che prende un DbContext nel suo costruttore e implementa IDisposable, si suppone che chiamerà dispose sul DbContext dal proprio metodo di smaltimento? Ho notato che EF UserStore per Identity non chiama dispose su dbcontext ma non mi sembra corretto, quindi sto cercando di capire perché non lo hanno fatto. –