Andiamo dritti al punto: cos'è davvero EF Core?

Se ti occupi di sviluppo con C#, probabilmente hai già sentito parlare di Entity Framework. Ma quando parliamo di entity framework net core, non stiamo parlando di una semplice versione aggiornata del vecchio EF6. È un rewrite completo.

Sostanzialmente, è l'ORM (Object-Relational Mapper) ufficiale di Microsoft che ci permette di interagire con il database usando oggetti C# invece di scrivere query SQL a mano per ogni singola operazione. Meno boilerplate, più logica di business.

Proprio così'.

Lavorare con EF Core significa astrarre lo strato dei dati. Invece di preoccuparti di come aprire una connessione o gestire i cursori, ti concentri sulle tue classi. Il framework si occupa di tradurre le tue espressioni LINQ in SQL efficiente (o quasi, se sai cosa stai facendo).

I tre approcci: quale scegliere?

Qui è dove molti sviluppatori si bloccano all'inizio. Esistono fondamentalmente due strade principali, più una via di mezzo che ormai sta scomparendo.

Code First è l'approccio dominante oggi. Scrivi le tue classi C#, definisci le relazioni e lasci che EF Core generi il database tramite le Migrations. È perfetto per i progetti nuovi dove hai il controllo totale sullo schema.

Un dettaglio non da poco: le migrazioni permettono di versionare il database esattamente come fai con il codice su Git. Fondamentale per il lavoro in team.

Poi c'è il Database First. Hai già un DB legacy, magari enorme e gestito da un DBA che non vuole sapere nulla del tuo codice C#? Usi il reverse engineering per generare le classi a partire dallo schema esistente. Meno flessibile nel tempo, ma salvavita in contesti aziendali complessi.

Esisteva poi l'approccio Model First (quello con i diagrammi visuali di Visual Studio), ma onestamente? È un ricordo del passato. Non perdeci tempo.

Il cuore pulsante: il DbContext

Se EF Core fosse un motore, il DbContext sarebbe l'albero motore. È la classe che coordina tutto: la connessione al database, il tracciamento delle modifiche e la configurazione dei modelli.

Molti commettono l'errore di istanziarlo a caso. Sbagliato. In un'applicazione .NET Core moderna, il DbContext va registrato nel contenitore di Dependency Injection (DI). In questo modo, il framework gestisce il ciclo di vita del contesto, solitamente con uno scope Scoped (una istanza per ogni richiesta HTTP).

Perché è importante? Perché un DbContext non è thread-safe. Se provi a usarlo in parallelo su più thread, l'app esploderà con errori di concurrency che ti faranno perdere ore di sonno.

Performance: dove EF Core può tradire

Non illudiamoci: usare un ORM ha un costo. A volte, se non stai attento, EF Core può generare query SQL mostruose o, peggio, causare il temuto N+1 problem.

Immagina di voler caricare una lista di ordini e, per ogni ordine, il nome del cliente. Se non specifichi come caricare i dati correlati, EF Core potrebbe fare una query per gli ordini e poi una query separata per ogni singolo cliente. Su 100 ordini, sono 101 chiamate al database.

Un suicidio prestazionale.

La soluzione? Eager Loading. Usa il metodo .Include() per dire a EF Core di fare una JOIN e portare tutto in un colpo solo. Oppure, se devi solo leggere dati per visualizzarli (senza modificarli), usa .AsNoTracking().

Semplice, veloce, efficace.

Il tracking è utile quando devi modificare un oggetto e salvarlo con SaveChanges(), ma consuma memoria e CPU. Se stai solo facendo una SELECT per una tabella di report, disabilitalo senza pietà.

Configurazione: Fluent API vs Data Annotations

Come diciamo a EF Core che una colonna deve essere unica o che un campo non può essere nullo? Abbiamo due modi.

Le Data Annotations sono quegli attributi come [Required] o [StringLength(100)] che metti sopra le proprietà della classe. Sono comode, immediate e visibili a colpo d'occhio.

Però sporcano il dominio. Il tuo modello di business inizia a dipendere da librerie specifiche del framework database. Non è l'ideale se punti a un'architettura pulita (Clean Architecture).

Qui entra in gioco la Fluent API. All'interno del metodo OnModelCreating, puoi definire ogni singolo dettaglio della tabella: indici, chiavi composte, vincoli di check. È molto più potente delle annotazioni e mantiene le tue classi POCO (Plain Old CLR Objects) pulite.

Il dilemma dei repository

C'è un dibattito infinito nella community .NET: serve ancora il Repository Pattern sopra EF Core?

Tecnicamente, DbContext è già un Repository e DbSet è un'implementazione di Unit of Work. Aggiungere un altro strato di astrazione spesso significa solo scrivere codice duplicato che non serve a nulla.

Tuttavia, se il tuo progetto è enorme e vuoi poter fare unit test senza toccare il database (usando mock), un repository può avere senso. Ma attenzione a non creare l'astrazione dell'astrazione. Se ti ritrovi a scrivere metodi come GetOrderByIdAsync che internamente chiamano solo _context.Orders.FindAsync(id), stai solo sprecando tempo.

Consigli per non impazzire con le Migrazioni

Le migrazioni sono fantastiche finché non devi fare un merge di due branch diversi che hanno entrambi modificato il database. Lì iniziano i dolori.

Ecco qualche regola d'oro:

  • Non modificare mai una migrazione già applicata in produzione. Crea una nuova migrazione per correggere l'errore.
  • Usa nomi descrittivi. AddUserTable è meglio di Migration1.
  • Controlla sempre il codice SQL generato prima di applicare la migrazione in ambienti critici. Puoi farlo con il comando script-migration.

Un ultimo suggerimento: per i progetti più complessi, considera l'uso di strumenti come Dapper per le query di sola lettura estremamente pesanti. EF Core è imbattibile per le scritture e le operazioni CRUD semplici, ma quando devi fare reportistica massiva su milioni di righe, a volte il SQL puro (o un micro-ORM) vince ancora.

Sintesi finale per lo sviluppatore

L'ecosistema entity framework net core è maturato incredibilmente. Dalle versioni iniziali di .NET Core fino alle ultime release di .NET 8 e oltre, le performance sono schizzate verso l'alto.

Il segreto per usarlo bene non è conoscere ogni singola funzione, ma capire cosa succede "sotto il cofano". Quando scrivi una riga di LINQ, chiediti: che tipo di SQL genererà questo?

Se impari a leggere i log delle query e a gestire correttamente il tracciamento dei dati, EF Core diventerà lo strumento più potente della tua cassetta degli attrezzi .NET.