Con l'uscita del Service Pack 1 del .NET Framework 3.5, Microsoft ha introdotto un nuovo ORM di nome Entity Framework, un progetto completamente diverso da LINQ to SQL in quanto con questo condivide solo il fatto di essere un ORM e di utilizzare LINQ come linguaggio principale di interrogazione.
Perché Entity Framework
Perché se esiste già LINQ to SQL, Microsoft ha creato un nuovo ORM? Esistono diverse spiegazioni per questa scelta da parte di Microsoft che hanno motivazioni più o meno valide. Mettendo da parte eventuali motivazioni commerciali, Entity Framework è comunque un ORM molto più completo rispetto a LINQ to SQL poiché copre esigenze che con quest'ultimo non possono essere soddisfatte. Per fare alcuni esempi, dei tre modi di rappresentare l'ereditarietà sul database, LINQ to SQL ne supporta solamente due al contrario di Entity Framework che li supporta tutti. Sempre parlando di mapping, LINQ to SQL obbliga a modellare le classi di dominio esattamente come le tabelle su cui queste mappano. Ad esempio, non è possibile avere una classe che contiene dati di due tabelle e viceversa. Entity Framework supera questa limitazione offrendo un mapping pressoché completo. Queste sono solo alcune delle caratteristiche che rendono Entity Framework un ORM più potente di LINQ to SQL in quanto ci sono anche una miglior gestione della concorrenza, una serie di driver di terze parti già pronti per supportare i database più diffusi, e altro ancora. Molte di queste caratteristiche verranno trattate nel corso dell'articolo.
I componenti di Entity Framework
Entity Framework è un ORM molto complesso e quindi la sua struttura è composta da diversi componenti. In questa sezione facciamo un po’ di luce sul funzionamento interno.
LINQ To Entities
Come si è avuto modo di apprendere dagli altri articoli facenti parte di questo sito, LINQ è un linguaggio di interrogazione universale poiché rende possibile interrogare ogni tipo di sorgente dati. LINQ to Entities è la specializzazione di LINQ che permette di scrivere query verso le classi presenti nel domain model. Sarà poi compito degli strati sottostanti convertire l'expression tree delle query nel linguaggio SQL a seconda del database. Poiché Entity Framework non obbliga ad avere le classi modellate esattamente come il database, con LINQ to Entities è ancora più evidente, rispetto a LINQ to SQL, che le query vengono fatte verso le classi di dominio.
LINQ to Entities supporta tutti gli operatori standard di LINQ con l'eccezione degli overload che accettano in input l'indice in cui si trova l'elemento. Questa limitazione è presente per ovvi motivi di traduzione in SQL. Oltre agli operatori standard, LINQ to Entities aggiunge un altro operatore (Include).
Entity SQL
Entity SQL è un linguaggio di interrogazione che ha le stesse potenzialità di LINQ to Entities ma a differenza di questo la query è espressa in formato stringa. Questa caratteristica offre il grande vantaggio di permettere di creare dinamicamente le query. Il motivo per cui esistono due differenti metodi per interrogare il domain model, sta nel fatto che quando si è iniziato a sviluppare Entity Framework LINQ ancora non esisteva e quindi si doveva ricorrere ad un metodo diverso. Allo stato attuale, a meno che non ci sia un problema insormontabile, LINQ to Entities è assolutamente da preferire a Entity SQL soprattutto per la semplicità di utilizzo. Per fare in modo che gli sviluppatori non dovessero imparare da zero un nuovo linguaggio di interrogazione, Entity SQL è stato costruito sulla base di SQL.
EDM Mapping
Questo componente si occupa del mapping tra le classi di dominio e le tabelle del database. La parte principale di questo strato è rappresentata dal file di mapping. Entity Framework, infatti, si appoggia ad un file XML esterno per descrivere come le classi devono essere mappate verso il database. In realtà bisogna tenere anche alcuni accorgimenti quando si scrivono le classi di dominio in quanto vanno utilizzati alcuni attributi per completare il mapping.
Il file di mapping viene definito EDM (Entity Data Model) ed è suddiviso in tre sezioni:
- Storage Schema Definition (SSDL): descrive il database
- Conceptual Schema Definition (CSDL): descrive le classi di dominio
- Mapping Schema Definition (MSL): descrive il mapping tra classi e database
Nel primo file viene inserita la descrizione del database con tutte le sue tabelle, i singoli campi, le relazioni, le chiavi primarie e tutto quanto è necessario per descrivere la struttura del database sottostante. Anche le funzioni e le stored procedure devono essere incluse in questa sezione.
Nel secondo file viene specificata la struttura delle classi di dominio con tutte le colonne, il tipo di dato che contengono, le relazioni con altre classi ecc.
Una volta che si ha a disposizione la descrizione dei due mondi da far colloquiare, nel terzo file si inseriscono le informazioni di mapping tra lo schema delle classi e le tabelle del database. Questo è probabilmente quello più complesso soprattutto quando entrano in gioco meccanismi di mapping complessi che non fanno un semplice mapping 1:1 tra tabella e classe (ereditarietà, tipi complessi, ecc).
Entity Framework è accompagnato da un designer visuale che viene aggiunto a Visual Studio e che copre buona parte delle necessità, lasciando a noi il solo scopo di disegnare visualmente le classi e facendo il lavoro sporco di generazione del codice e del file di mapping. Tuttavia, non tutte le operazioni possono essere svolte dall'editor visuale quindi conoscere la sintassi del file di mapping risulta fondamentale in alcuni casi. Questa struttura è molto complessa e merita un articolo a parte che verrà pubblicato in futuro. L'ultima cosa da dire sul mapping è che l'editor visuale genera un file con estensione EDMX che contiene tutte e tre le sezioni necessarie. Poiché il runtime di Entity Framework ha bisogno dei tre file distinti, questi vengono creati suddividendo a runtime il file EDMX. Questo significa che anche se non si vuole usare il file EDMX, ma costruire a mano il codice XML, lo si può fare tranquillamente.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Generare velocemente pagine CRUD in Blazor con QuickGrid
Utilizzare il metodo CountBy di LINQ per semplificare raggruppamenti e i conteggi
Ottimizzare il mapping di liste di tipi semplici con Entity Framework Core
Persistere la ChatHistory di Semantic Kernel in ASP.NET Core Web API per GPT
Usare le navigation property in QuickGrid di Blazor
Le novità di Entity Framework 8
Change tracking e composition in Entity Framework
Filtering sulle colonne in una QuickGrid di Blazor
Filtrare i dati di una QuickGrid in Blazor con una drop down list
Utilizzare EF.Constant per evitare la parametrizzazione di query SQL
Supporto ai tipi DateOnly e TimeOnly in Entity Framework Core