Nel precedente articolo abbiamo visto le novità introdotte da Entity Framework 4.1 e come queste migliorino il nostro codice di accesso ai dati. In questo articolo analizzeremo più a fondo quella che certamente è la più grande novità introdotta con Entity Framework 4.1: Code-First. Code-First è la feature che ci permette di mappare le classi di dominio utilizzando solamente il codice ed evitando quindi l'uso del designer di Visual Studio.
Nella prima parte di quest'articolo vedremo come eseguire le operazioni di mapping più basilari come il mapping one-to-one tra una classe ed una tabella, la personalizzazione del mapping ed il mapping delle associazioni tra le classi del modello. Nella seconda parte vedremo una funzionalità di mapping avanzata come il mapping dell'ereditarietà.
Come abbiamo visto nel precedente articolo, abbiamo a disposizione due modi per personalizzare il mapping: DataAnnotation o codice. Le DataAnnotationsono molto comode perché permettono di personalizzare il mapping con dei semplici attributi su classi e proprietà. Tuttavia, le DataAnnotation"sporcano" le classi di dominio che in realtà dovrebbero contenere solo codice di business e non codice di mapping. Se questo non rappresenta un problema (e se si possono modificare le classi di dominio), si possono tranquillamente utilizzare le DataAnnotation, altrimenti si deve ricorrere al codice. Inoltre le DataAnnotation non coprono tutte le possibilità di mapping e quindi in alcuni siamo costretti a ricorrere al codice. Quando possibile, nell'articolo verranno illustrate entrambe le tecniche, li dove le DataAnnotation non coprono la funzionalità necessaria, ricorreremo al codice.
Creare le classi di dominio
Creare le classi di dominio via codice è un'operazione estremamente semplice. Nel caso in cui una classe abbia lo stesso nome della tabella verso cui è mappata e nel caso in cui le proprietà della classe abbiano lo stesso nome delle rispettive colonne della tabella, non dobbiamo fare assolutamentenulla se non scrivere il codice della classe. Prendiamo come esempio la seguente classe di dominio:
public class Product { public int Id { get; set; } public string Name { get; set; } public decimal UnitPrice { get; set; } }
e la seguente classe di contesto:
public class AppContext : DbContext { public DbSet<Product> Products { get; set; } }
Se sul database esiste una tabella che si chiama Products (il nome dell'entity set esposto dal contesto) le cui colonne hanno gli stessi nomi delle proprietà della classe Product, il codice appena visto è tutto ciò di cui abbiamo bisogno per mappare la classe verso la tabella.
Per convenzione, se la classe contiene una proprietà di nome Id o Key oppure il cui nome corrisponde al formato <NomeClasse>Id o<NomeClasse>Key, questa proprietà diventa automaticamente la chiave primaria. Inoltre, se la chiave è di tipo numerico, questa viene automaticamente trattata come un Identity e quindi Entity Framework si aspetta che il suo valore sia calcolato dal database.
Grazie a queste convenzioni (il nome della tabella corrisponde al nome dell'entity set, la chiave primaria ha un nome preciso, le proprietà della classe hanno lo stesso nome delle colonne), il codice che dobbiamo scrivere per eseguire il mapping è veramente minimo.
Nel proseguio dell'articolo utilizzeremo un dominio composto da più classi ed il cui design è mostrato nella figura 1.
Questo dominio mappa sulle tabelle esposte nella figura 2.
Come possiamo vedere, tra le classi di dominio e le tabelle del database ci sono alcune differenze:
- le classi Customer e GoldCustomer (GoldCustomer eredita da Customer) mentre nel database abbiamo una tabella Customers che contiene i dati per entrambe le classi.
- Nel dominio esiste il complex type AddressInfo che non ha una controparte in nessuna tabella.
- Le classi Customer e Order hanno rispettivamente la proprietà Address e ShippingAddress che sono delle complex property di tipo AddressInfo, mentre le tabelle Customer e Orders hanno i campi direttamente nella tabella.
- La tabella Customer ha una colonna Type che specifica se la riga contiene i dati di un'istanza di un Customer o di un GoldCustomer.
- La classe OrderDetail mappa sulla tabella Details. Inoltre, La classe OrderDetail ha una proprietà Total che rappresenta il risultato della moltiplicazione della proprietà Quantity con la proprietà UnitPrice e che non ha una controparte nel database. Infine, la foreign key property tra OrderDetail e Product si chiama ProdId, mentre sul database la colonna si chiama ProductId
Prima di vedere come eseguire il mapping tra le varie classi, vediamo come sfruttare le convenzioni di default di Entity Framework Code-First.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Utilizzare la funzione EF.Parameter per forzare la parametrizzazione di una costante con Entity Framework
Ottimizzare le performance usando Span<T> e il metodo Split
Ottimizzare le pull con Artifact Cache di Azure Container Registry
Usare i settings di serializzazione/deserializzazione di System.Text.Json di ASP.NET all'interno di un'applicazione non web
Generare velocemente pagine CRUD in Blazor con QuickGrid
Come EF 8 ha ottimizzato le query che usano il metodo Contains
Utilizzare il metodo ExceptBy per eseguire operazione di sottrazione tra liste
Filtrare i dati di una QuickGrid in Blazor con una drop down list
Cancellare una run di un workflow di GitHub
Migliorare la scalabilità delle Azure Function con il Flex Consumption
Definire stili a livello di libreria in Angular
Utilizzare il nuovo modello GPT-4o con Azure OpenAI