Quando da ASP.NET Core vogliamo sfruttare Entity Framework per interagire con il database, tipicamente usiamo il metodo AddDbContext per registrare il nostro DbContext nell'IoC container.
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddDbContext<MyContext>(options => options.UseSqlServer(Configuration.GetConnectionString("MyContext"))); }
A questo punto, come sappiamo, possiamo iniettare il DbContext all'interno di un controller e usarlo per eseguire query:
public class IndustryController : ControllerBase { private MyContext _myContext; public IndustryController(MyContext myContext) { _myContext = myContext; } [HttpGet] public IEnumerable<Industry> Get() { return _myContext.Industries; } }
Immaginiamo ora, però, di voler eseguire più operazioni in parallelo nella stessa chiamata. Per esempio vogliamo effettuare due query indipendenti, per poi manipolarne il risultato in memoria prima di restituirlo. Purtroppo, in questi casi, il metodo visto finora non va bene e il motivo è presto detto: DbContext non è thread safe, e quindi non può essere sfruttato da più thread contemporaneamente. Per di più, è registrato come Scoped, e pertanto anche richiedendo esplicitamente nuove istanze, ci verrebbe restituita sempre la stessa.
Come possiamo procedere allora? La soluzione sta nel metodo AddDbContextFactory:
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddDbContextFactory<MyContext>(options => options.UseSqlServer(Configuration.GetConnectionString("MyContext"))); }
Questo metodo, ci permette di iniettare un oggetto IDbContextFactory, tramite cui possiamo facilmente costruire istanze di DbContext secondo le nostre necessità:
private IDbContextFactory<MyContext> _factory; public IndustryController(IDbContextFactory<MyContext> factory) { _factory = factory; } [HttpPost] public async Task<IActionResult> DoSomethingInParallel() { var t1 = Task.Run(async () => { using (var ctx = _factory.CreateDbContext()) { // ... do something here } }); var t2 = Task.Run(async () => { using (var ctx = _factory.CreateDbContext()) { // ... do something else here } }); await Task.WhenAll(t1, t2); return this.Ok(); }
Tutto ciò che dobbiamo fare è invocare il metodo CreateDbContext per ottenere un nuovo DbContext pronto all'uso. Attenzione però a un aspetto fondamentale: l'IoC container non è a conoscenza di queste istanze, e pertanto non ne chiamerà il Dispose al termine della richiesta - questa resterà una nostra responsabilità.
L'ultima nota da sottolineare è che AddDbContextFactory registra sia un IDbContextFactory, che un normale DbContext come scoped. Questo vuol dire che potremo iniettare entrambe le dipendenze, secondo le nostre necessità:
public IndustryController(IDbContextFactory<MyContext> factory, MyContext myContext) { _factory = factory; _myContext = myContext; }
Questa è una peculiarità di Entity Framework Core 6.0, se stiamo ancora utilizzando la versione precedente dovremo registrare le due dipendenze separatamente.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Sfruttare GPT-4o realtime su Azure Open AI per conversazioni vocali
Migliorare l'organizzazione delle risorse con Azure Policy
Creare una libreria CSS universale: Nav menu
Eseguire query per recuperare il padre di un record che sfrutta il tipo HierarchyID in Entity Framework
Creare una custom property in GitHub
Definire stili a livello di libreria in Angular
Hosting di componenti WebAssembly in un'applicazione Blazor static
Il nuovo controllo Range di Blazor 9
Path addizionali per gli asset in ASP.NET Core MVC
Bloccare l'esecuzione di un pod in mancanza di un'artifact attestation di GitHub
Eseguire i worklow di GitHub su runner potenziati
Disabilitare automaticamente un workflow di GitHub (parte 2)
I più letti di oggi
- Simulare Azure Cosmos DB in locale con Docker
- Utilizzare il metodo Index di LINQ per scorrere una lista sapendo anche l'indice dell'elemento
- ecco tutte le novità pubblicate sui nostri siti questa settimana: https://aspit.co/wkly buon week-end!
- .NET Conference Italia 2024 - Milano
- .NET Conference Italia 2023 - Milano e Online