Accesso ai dati in .NET quando performance, coerenza e manutenzione contano davvero

Qui trovi Entity Framework Core, LINQ e data access spiegati per evitare query tossiche, modelli incoerenti e scelte che rallentano ogni evoluzione del software nel momento peggiore.

Il data layer non è un dettaglio: è dove si perde il controllo

La maggior parte dei problemi di performance e manutenibilità nei sistemi .NET che analizzo ha origine nello strato dati.

Non nel modello di dominio, non nell'architettura applicativa: nel modo in cui si accede al database.

Query N+1 generate senza accorgersene da Entity Framework.

Caricamento di interi oggetti quando servono tre campi.

Transaction aperte per tutta la durata di una richiesta HTTP.

Indici mancanti su colonne usate in ogni WHERE clause.

Mapping tra tabelle e oggetti che forza strutture di query innaturali.

Questi non sono errori rari.

Sono pattern ricorrenti in quasi ogni codebase che cresce senza attenzione al data layer.

Il problema non è Entity Framework: è usarlo senza capire cosa genera.

Questa categoria esiste per colmare questo gap: non tutorial su come configurare il DbContext, ma ragionamenti su come progettare l'accesso ai dati in modo che il sistema rimanga veloce, coerente e modificabile mentre i requisiti cambiano.

Entity Framework Core: quando usarlo bene e quando affiancarlo a Dapper

Entity Framework Core è lo strumento giusto per la maggior parte dei scenari di accesso ai dati in .NET.

Gestisce il mapping, il change tracking, le migrazioni e l'astrazione dal dialetto SQL specifico.

Per operazioni CRUD, query moderate e manutenzione del schema, è la scelta più produttiva.

I problemi emergono quando si usa EF Core per tutto senza misurare.

Le query generate automaticamente non sono sempre ottimali.

Il change tracker ha un costo.

Il caricamento eager con Include può generare join pesanti dove una query separata sarebbe più efficiente.

Dapper entra in gioco per le query complesse dove serve controllo totale sull'SQL: report con aggregazioni complesse, query su viste materializzate, operazioni bulk, stored procedure legacy.

Non sostituisce EF Core: lo affianca nei casi specifici dove il controllo dell'SQL è più importante della produttività del mapping automatico.

Il pattern che uso più spesso è EF Core per write e operazioni transazionali, Dapper o query SQL dirette per read complesse e report.

Non è un'architettura sofisticata: è pragmatismo applicato.

Query efficienti in EF Core: le insidie da conoscere

Il problema N+1 è la trappola più comune con EF Core: per ogni elemento di una lista si esegue una query aggiuntiva invece di un join.

Si manifesta quando si itera su una collection e si accede a navigation property non caricate, e può trasformare una lista di cento elementi in centocento query al database.

La soluzione è il caricamento esplicito con Include() per le navigation property necessarie, oppure la proiezione con Select() per caricare solo i campi necessari senza navigare l'intero oggetto.

La proiezione è spesso la scelta migliore per le query di lettura: genera SQL più semplice, carica meno dati e non attiva il change tracker.

AsNoTracking() è un altro strumento fondamentale per le query di sola lettura: disabilita il change tracking e riduce l'allocazione di memoria.

Su query che restituiscono centinaia di oggetti, la differenza è misurabile.

Lo strumento per diagnosticare i problemi è EnableDetailedErrors() e il logging delle query SQL generato da EF Core.

In sviluppo, vedere l'SQL generato è indispensabile.

In produzione, Application Insights o il query store di SQL Server rivelano le query lente prima che diventino incidenti.

Migrazioni e schema evolution: come non avere paura del database

Le migrazioni EF Core sono uno degli strumenti più sottovalutati dell'ecosistema.

Permettono di versionare lo schema del database insieme al codice, di applicare modifiche in modo ripetibile e di rollback quando necessario.

Le insidie delle migrazioni vengono quasi sempre da migrazioni troppo grandi o distruttive applicate senza piano.

Rinominare una colonna in una singola migrazione genera una DROP e una ADD, non un RENAME: tutti i dati di quella colonna vanno persi se non si gestisce esplicitamente la trasformazione.

Le migrazioni che modificano dati esistenti devono essere testate su una copia del database di produzione prima dell'applicazione.

Il pattern che riduce il rischio è la migrazione in due fasi per i cambiamenti breaking: prima si aggiunge la nuova struttura mantenendo quella vecchia, si migra il codice a usare la nuova struttura, poi in una release successiva si rimuove quella vecchia.

Più lento, molto più sicuro.

In produzione le migrazioni non dovrebbero mai girare automaticamente all'avvio dell'applicazione.

Devono essere script SQL revisionati, applicati in modo controllato e registrati come parte del processo di deploy.

Analisi, casi e articoli su Entity Framework Core, LINQ e data access

2 articoli trovati

Quando lo strato dati decide la qualita del software

Lo strato dati decide la qualita del software quando le performance contano, le query diventano complesse e il modello deve evolvere senza rompere il resto del sistema. E qui che buone scelte su ORM, mapping e database incidono davvero su costi e affidabilita.

Tecnologie correlate alla gestione dati

Cos'è Entity Framework

Entity Framework? È il ponte tra il tuo codice e il database. Scopri cos’è e perché è diventato uno strumento essenziale per gli sviluppatori moderni.

Cos'è SQL Server

Scopri cos'è SQL Server, il database relazionale di Microsoft per gestire dati aziendali con performance, sicurezza e integrazione .NET nativa.

Cos'è Dapper

Scopri cos'è Dapper, come funziona il micro-ORM di Stack Overflow per .NET e quando usarlo al posto di Entity Framework.

Domande frequenti

Entity Framework Core e la scelta giusta per applicazioni CRUD standard, quando vuoi migrazioni gestite, change tracking automatico e query costruite con LINQ. Dapper e preferibile per query complesse, report su grandi volumi di dati, stored procedure esistenti o quando il controllo sul SQL generato e critico per le performance. In molte applicazioni enterprise si usano entrambi: EF Core per le operazioni standard, Dapper per le query analitiche.

Le migrations sono snapshot incrementali dello schema del database generati da EF Core a partire dal modello C#. Ogni migration descrive le differenze rispetto allo stato precedente e contiene il codice per applicare e annullare la modifica. Permettono di evolvere lo schema in modo versionato e reversibile, applicabile via CLI (dotnet ef database update) o automaticamente all'avvio dell'applicazione.

Le ottimizzazioni piu impattanti sono: usare AsNoTracking per le query di sola lettura, proiettare solo le colonne necessarie con Select invece di caricare l'intera entita, evitare il problema N+1 con Include o query split, e usare query raw SQL via FromSqlRaw per i casi complessi. Application Insights o EF Core logging aiutano a individuare le query lente in produzione.

SQL Server e la scelta naturale per applicazioni enterprise che girano su Azure o Windows con integrazione Microsoft completa. PostgreSQL e preferito in contesti open source, Linux o cloud multi-vendor per le sue performance e la ricchezza di tipi. Cosmos DB e adatto a dati non strutturati, scale globale e throughput elevato. La scelta dipende dal tipo di dati, dal cloud provider e dai requisiti di scalabilita.

Fonti e riferimenti

Backend designing with Entity Framework Core

Una lunga disamina su Entity Framework Core che va oltre l’uso dell’API e analizza capacità, concetti fondamentali, usabilità e grado di maturità del framework. Ha il respiro di un vero approfondimento tecnico, con un livello di contenuto sufficientemente solido da sembrare un paper serio e meno noioso dei soliti manuali.