Avere più di un contesto di entità

asp.net-core asp.net-core-mvc entity-framework-core

Domanda

Diciamo che ho esteso il framework di identità dbContext per creare il mio, e ho il nostro controller autenticato che viene iniettato con dbContext e recupera un'entità correlata all'attuale ApplicationUser , l'entità framework riguarderà le due entità che portano a un errore del server perché di riferimenti circolari.

Non vogliamo serializzare riferimenti circolari.

Quindi creiamo un nuovo dbContext nel metodo che istanzia un nuovo dbcontext e interroga le entità non correlate, questo funzionerà. Ma questo non è testabile , non vogliamo che il nostro controller dipenda strettamente da dbContext , vogliamo che venga iniettato.

Quindi aggiungiamo un secondo parametro, nel costruttore, sfortunatamente questo farà sì che il sistema inietti lo stesso dbContext due volte , non così utile.

Abbiamo provato a creare una classe fakeDbContext che eredita da dbContext e aggiungila servizi e usarla, ma ora abbiamo due dbcontext , che possono potenzialmente generare migrazioni e configurazioni ed errori ...

Qual è il modo giusto di farlo nella nuova MVC6?

Modificare...

Ho scoperto che se il mio controller richiede un oggetto IEnumerable<dbContext> ottengo tutto l'oggetto registrato come servizio di quel tipo, quindi raddoppiamo solo la parte in startup.cs dove aggiungiamo il dbContext nell'area di registrazione del servizio ne ottengo due. ..

Lo svantaggio qui è che non so che uno è vergine , sembra che vada in ordine di registrazione, ma non ho idea, se questo cambierà.

Modifica 2 ...

Ho creato una classe TransientDbService che ha solo un metodo factory che prende IserviceProvider , lo usa per ottenere le opzioni per costruire il dbContext e quindi esporlo. L'ho registrato come transitorio, quindi nel controller ho bisogno di questo tipo di servizio.

lo svantaggio qui è che se avrò mai bisogno di un terzo dbContext dovrei scrivere più codice, più codice significa errori e mantenerlo.

Modifica 3 ...

Non avendo affatto due dbContext. Le seguenti impostazioni mi consentono di non avere relazioni valorizzate.

Database.ChangeTracker.QueryTrackingBehavior = Microsoft.Data.Entity.QueryTrackingBehavior.NoTracking;

Lo svantaggio qui è che non posso usare il mio grafico del modello, rendendo tutto più complesso ...

Modifica 4 ...

https://github.com/aspnet/DependencyInjection/issues/352

Risposta accettata

Hai ragione di pensare che in alcuni casi nessuna query di tracciamento sarà di aiuto, ma altre volte dovrai creare più di una istanza di DbContext creata.

Normalmente si utilizza il AddDbContext<TContext>() all'avvio per assicurarsi che venga creata un'istanza del tipo di contesto per ogni richiesta e che vengano impostate le giuste DbContextOptions e il provider di servizi. Quando hai bisogno di deviare da questo modello hai alcune opzioni, ad esempio:

  1. Includere un costruttore nella classe DbContext derivata che accetta un IServiceProvider e lo passa al costruttore base. Assicurati che il tuo controller IServiceProvider . Una volta fatto questo dovresti essere in grado di creare manualmente DbContext con qualcosa del genere:

    using(var context1 = new MyDbContext(serviceProvider), var context2 = new MyDbContext(serviceProvider)) { ...

  2. Per evitare di dover modificare le firme del costruttore sul tipo DbContext derivato, è possibile sfruttare la classe DbContextActivator (è il nostro spazio dei nomi interno), ad esempio:

    using(var context1 = DbContextActivator.CreateInstance<MyDbContext>(serviceProvider), var context2 = DbContextActivator.CreateInstance<MyDbContext>(serviceProvider) {...

Nota: se si sta ancora utilizzando AddDbContext<MyDbContext>(options => ...) all'avvio, queste opzioni dovrebbero essere automaticamente selezionate dal fornitore di servizi. Ma puoi anche scegliere di includere DbContextOptions come parametro nel costruttore o sovrascrivere il metodo OnConfiguring() per quello.

Vi sto dando esempi che creano due DbContexts separati in un blocco using, ma dovreste anche essere in grado di mescolare quelli con il DbContext "per richiesta" normale che vi verrebbe iniettato nel costruttore del controller.

Oltre a queste opzioni attualmente disponibili, ho creato un nuovo problema per tenere traccia di altri possibili miglioramenti su come creare più istanze dello stesso tipo DbContext nella stessa richiesta:

https://github.com/aspnet/EntityFramework/issues/4441




Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché