Le novità di Entity Framework 4
a cura di Antonio Catucci (requisiti: Visual Studio 2010)Premessa
Entity Framework è l'ORM (Object-Relational Mapping) targato Microsoft, introdotto in .NET Framework 3.5, che consente la gestione della persistenza dei dati e la manipolazione degli stessi mediante un approccio completamente object oriented. Con il rilascio di .NET Framework 4 RC e Visual Studio 2010 RC viene rilasciata la seconda versione di Entity Framework (EF), meglio nota come 'v4' per allinearla alla versione del framework, che introduce molte novità sia per quanto riguarda il 'core' che il designer integrato in Visual Studio 2010.
In questo articolo faremo una carrellata delle novità più importanti.Foreign Key
In EFv1 le relazioni tra le entità sono rappresentate dalle Navigation Properties e sono l'unico accesso alle entità collegate (siano esse delle collection o singole entità). Se da un lato questo è ottimo da un punto di vista OOP (Object Oriented Programming), dall'altro diventa scomodo quando si devono creare nuove istanze di entità relazionate con altre.
Supponiamo di avere nel nostro database due tabelle Product e Category in relazione tra loro mediante il campo CategoryId (presente in entrambe). Il modello dati (edmx) rappresenta questa relazione con una navigation property in Product chiamata Category di tipo Category (entità). In EFv1 per aggiungere un nuovo prodotto associato alla categoria 5 si dovrebbe scrivere una cosa del genere:Using Context Dim p As New Product With { .ProductName = "New product", .ReorderLevel = 20} Dim Cat = Context.Categories.First(Function(c) c.CategoryID = 5) p.Category = Cat Context.Products.AddObject(p) Context.SaveChanges() End UsingQuesto approccio ha il grosso svantaggio di accedere al database per recuperare la categoria 5 e, sebbene esista un modo per evitarlo, è comunque necessario creare un oggetto di tipo Category da assegnare all'entità Product per specificare il solo ID. In EF4 il problema viene risolto 'semplicemente' esponendo la chiave esterna mediante una proprietà scalare nell'entità in cui è utilizzata. Nel nostro esempio, in Product troveremo la proprietà CategoryID che ci permette di riscrivere il codice precedente come segue:
Using Context Dim p As New Product With { .ProductName = "New product", .CategoryId = 5, .ReorderLevel = 20} Context.Products.AddObject(p) Context.SaveChanges() End UsingSicuramente molto più semplice!
Supporto per le entità POCO
Questa caratteristica è stata chiesta a furor di popolo e il team di EF non si è fatto pregare, aggiungendo il supporto per le entità POCO (Plain Old CLR Object - ovvero entità 'semplici', cioè che non ereditano da EntityObject), eliminando così dipendenze dall'assembly System.Data.Entity e quindi da Entity Framework stesso.
Un esempio di entità POCO è la seguente:Partial Public Class Category Public Overridable Property CategoryID As Integer Public Overridable Property CategoryName As String Public Overridable Property Description As String Public Overridable Property Picture As Byte() Public Overridable Property Products As ICollection(Of Product) End Class
Grazie a questa caratteristica, ad esempio, diventa molto più semplice serializzare le entità, perché non contengono tutte le informazioni supplementari incluse ereditando da EntityObject. Inoltre, non avendo dipendenze con l'assembly di Entity Framework, è possibile utilizzare le nostre entità anche in altri ambienti.
Naturalmente il file .edmx che contiene il mapping delle entità continua ad esistere, ma senza il relativo codice vb o cs delle entità, cosa che si ottiene impostando la proprietà Code Generation Startegy su None.
Supporto Lazy Loading
EF di default interroga e restituisce solo le entità specificate nella query LINQ, per evitare un sovraccarico inutile durante il recupero dei dati.Se si ha la necessità di accedere alle entità associate, è possibile utilizzare l'extension method Include() direttamente nella query, oppure caricare esplicitamente l'entità associata desiderata con il metodo Load().
In EF4 viene aggiunto il Lazy Loading, cioè il caricamento implicito di dati nel momento in cui si accede per la prima volta a una entità associata anche senza dover utilizzare l'extension Include().
Il Lazy Loading si abilita impostando la proprietà LazyLoadingEnabled dell'oggetto ContextOptions a True.
Da notare che questo comportamento è abilitato di default dal designer, quindi bisogna tenerlo presente quanso si eseguono le query.
Un esempio di lazy loading implicito è il seguente:
Dim c = Context.Customers.First(Function(c) c.CustomerID = "AFKI") Console.WriteLine("Customer {0} - Orders: {1}", c.CustomerId, c.Orders.Count)Come si può notare, la query LINQ restituisce solo l'entità Customers, mentre, durante la stampa a video, viene visualizzato anche il numero degli ordini attraverso la navigation property Orders: è solo con la chiamata c.Orders.Count() che viene eseguita una query sul database per ottenere il numero totale degli ordini.
Model First design
Fino ad ora, l'approccio di EF è stato quello di mappare un database con un modello a oggetti. Con EF4 è possibile il percorso inverso, ovvero creare il modello a oggetti e generare il database sulla base di esso. A tal proposito esiste una estensione molto utile in Visual Studio 2010 che permette, mediante una interfaccia grafica, oltre che di poter scegliere quale strategia applicare per la generazione del database (basata sui template T4), anche di eseguire il deploy su database :![]()
Potete trovare tutto questo nel Database Generation Power Pack scaricabile da visualstudiogallery.
Supporto per template T4
Con Visual Studio 2010 il designer di EF si arricchisce di una funzionalità davvero molto potente: l'integrazione di T4 Code Generation per la generazione automatica di codice.Grazie a questa caratteristica (comunque utilizzabile anche in Visual Studio 2008), la personalizzazione del codice generato dal designer per il modello delle entità diventa non solo molto semplice, ma anche estendibile, perché è possibile creare i propri template per la generazione di codice ad-hoc.
Attualmente in Visual Studio 2010 sono disponibili 3 template già pronti, utilizzabili, rispettivamente, per la generazione di entità tipizzate (che è anche quello utilizzato di default), di entità POCO e di entità Self-Tracking.
I template T4 sono utilizzati anche per la generazione degli script SQL nell'approccio Model-First.
Migliorato il supporto per le Stored Procedure
Il mapping delle stored procedure è una caratteristica introdotta sin dalla prima versione di EF, ma, purtroppo, questo supporto era davvero minimale, inizialmente. Le cose sono decisamente migliorate con EF4: infatti è possibile, a esempio, mappare stored procedure che restituiscono tipi 'anonimi' non presenti nel modello dati, mediante la creazione di ComplexType specifici. Tutto questo con il supporto del designer:![]()
La chiamata a questa stored procedure sarebbe:
Using db As New NorthwindEntities Dim r = db.GetEmployeeSlasesByCountry(New DateTime(1996, 1, 1), New DateTime(1996, 12, 31)) End UsingDove la variabile 'r' è un tipo ObjectResult(Of EmployeeSales).
Supporto dei ComplexType nel designer
Una richiesta molto gettonata dagli sviluppatori è stata la gestione dei Complex Type direttamente nel designer. In Visual Studio 2010 è, infatti, possibile creare o fare il refactoring delle proprietà in tipi complessi semplicemente selezionando le proprietà da trasformare e selezionando l'opzione 'Refactor into New Complex Type' dal menu contestuale:![]()
Pluralization
Un fastidioso inconveniente del designer di EFv1 è la totale assenza di una nomenclatura per distinguere le entità dai relativi EntitySet. Infatti quello che accade è che sia l'entità che l'EntitySet prendono il nome originale della relativa tabella nel database rendendo, di fatto, il codice poco leggibile. In EF4 è stato aggiunto il supporto per la pluralization in fase di creazione del modello delle entità come si nota dalla figura seguente:![]()
Il cui risultato è il seguente:
![]()
Come si può vedere dalle immagini precedenti, il plurale viene applicato all'EntitySet Name e alle navigation property con relazioni 1 a molti (1..*) e molti a molti (*..*), mentre in tutti gli altri casi il nome viene generato al singolare. Il risultato è un codice sicuramente molto più leggibile!
Da tenere presente che questa opzione funziona solo con la lingua inglese.Conclusioni
Quelle esposte sono solo alcune delle novità introdotte in Entity Framework 4. Infatti, esistono altri miglioramenti introdotti in questa versione come l'ottimizzazione del codice SQL generato a seguito di query LINQ , oppure il supporto migliorato per lo sviluppo di applicazioni N-Tier, come la possibilità di creare entità con il supporto del Change Tracking.
Certamente queste novità rendono questa nuova versione di Entity Framework molto più interessante e potente rispetto alla precedente.