3. Introduzione Un framework di ObjectRelationalMapping (ORM) ha l’obiettivo di avvicinare la logica di interfacciamento alle basi di dati, alla logica della programmazione orientata agli oggetti Vantaggi Consente di colmare il gap che esiste tra il modello relazionale ed il modello objectoriented Riduce drasticamente il codice scritto per interfacciarsi ai database Permette di rendere lo strato di accesso ai dati indipendente dallo specifico RDBMS utilizzato Favorisce lo spostamento della logica applicativa dalle stored procedure al codice
4.
5. Introduzione ADO.NETEntityFramework è la proposta di Microsoft nel mercato degli ObjectRelational Mapper (ORM) Storia V1 - .NET Framework 3.5 SP1 V4 - .NET Framework 4
6. Introduzione ADO.NETEntityFramework basa il suo funzionamento su un Entity Data Model composto dai seguenti tre schema XML: Conceptual schema definitionlanguage (CSDL) Definisce lo schema concettuale del modello objectoriented dei dati Store schema definitionlanguage (SSDL) Definisce lo schema di persistenza su database dei dati Mappingspecificationlanguage (MSL) Definisce il mapping tra CSDL e SSDL
7. Introduzione E’ possibile generare l’Entity Data Model in tre modi: Database first Visual Studio li genera a partire da un database già esistente Di default per ogni tabella viene generata una classe e le relazioni tra le tabelle diventano navigationproperties Model first (introdotto con Visual Studio 2010) Si usa il designer di Visual Studio per realizzare prima il modello concettuale e successivamente generare gli script per il database Code first (a partire da EntityFramework CTP 4) Si parte dalle classi del proprio modello
8. Introduzione Architettura layered ObjectServices Forniscono l’accesso ai dati mediante l’ObjectContext e “contenitori di oggetti” denominati ObjectSet EntityClient Data Provider Gestisce le connessioni e converte le query dal modello concettuale al modello fisico utilizzando l’EDM ADO.NET Data Providers Eseguono l’accesso al database
9. Introduzione ADO.NETEntityFramework è un’API indipendente dal database sottostante Un database, per essere compatibile, deve fornire un provider ADO.NET in grado di supportare EntityFramework Il .NET Framework 3.5 SP1 o superiore integra un provider per l’accesso ai dati (SqlClient) compatibile con SQL Server 2000, 2005, 2008 e Azure Esistono provider (gratuiti o a pagamento) per tutti i più diffusi RDBMS: Oracle, MySql, PostgreSQL, DB2, SQLite, Sybase, ecc…
10. Operazioni sul database L’interrogazione al modello concettuale è possibile sfruttando tre diversi formalismi: Entity SQL Query Builder Method LINQ toEntities
11. Operazioni sul database Entity SQL E’ il modo più prestante di eseguire interrogazioni mediante l’EntityFramework E’ un linguaggio SQL-like molto simile a T-SQL, usato per interrogare il modello concettuale string selectCustomers = "SELECT VALUE Customer From NorthwindEntities.Customers as Customer where Customer.CustomerID = @id"; ObjectQuery<Customers> query = new ObjectQuery<Customers>(selectCustomers, entities); query.Parameters.Add(new ObjectParameter("id", "ALFKI"));
12. Operazioni sul database QueryMethod Rappresentano una serie di metodi disponibili per l’ObjectSet che facilitano la costruzione di query rispetto all’uso diretto dell’Entity SQL E’ una soluzione che si pone in posizione intermedia tra LINQ e l’Entity SQL I metodi di query sono ottimizzati per introdurre un overhead minimo rispetto all’Entity SQL var query = entities.Customers.Where("it.CustomerID = @id", new ObjectParameter("id", "ALFKI"));
13. Operazioni sul database LINQ toEntities Poiché gli ObjectSet implementano l’interfaccia IQuerable, possono essere interrogati utilizzando LINQ sia con la methodsyntax, che con la querysyntax //methodsyntax var customers = entities.Customers.Where(c => c.CustomerID == "ALFKI"); //querysyntax varcustomers = fromcustomer in entities.Customers wherecustomer.CustomerID == “ALFKI” selectcustomer;
14. Operazioni sul database L’esecuzione delle interrogazioni su database viene effettivamente eseguita solo nei seguenti casi: Viene enumerato il risultato della query Viene applicato l’operatore First o Any con LINQ La query è, pertanto, eseguita solo quando i suoi risultati sono effettivamente necessari var customers = entities.Customers.Where(c => c.CustomerID == "ALFKI");foreach (var customer in customersWithOrders) { … } Esecuzione query
16. Operazioni sul database Create L’operazione di create, cioè di inserimento di un nuovo record è supportata semplicemente creando una nuova istanza della classe corrispondente ed aggiungendola all’ObjectContext con il metodo AddObject Delete Analogamente all’operazione di inserimento, la cancellazione è supportata richiamando semplicemente il metodo DeleteObject dell’ObjectContext Customers customer = new Customers();customer.CustomerID = "KILOP";customer.CompanyName = "Kilop";entities.Customers.AddObject(customer); entities.Customers.DeleteObject(customer);
17. Operazioni sul database Update Normalmente l’ObjectContext tiene traccia dello stato di tutti gli oggetti restituiti da una interrogazione Questa funzionalità gli consente di persistere su database le modifiche effettuate sulle proprietà degli oggetti Persistenza Le operazioni di Insert, Update e Delete vengono persistite solo alla chiamata del metodo SaveChanges dell’ObjectContext Il metodo SaveChanges viene sempre eseguito in transazione Se un’operazione comporta una modifica ad altre tuple del database (ad esempio attraverso trigger), è necessario chiamare il metodo Refresh per aggiornare lo stato delle entità
19. Gestione delle connessioni ADO.NETEntityFramework apre e chiude le connessioni automaticamente per il tempo strettamente necessario all’esecuzione di un’operazione E’ possibile anche gestire manualmente le connessioni, ma in tal caso è necessario ricordarsi di richiamare il metodo Close o Dispose affinché Entity Framework riprenda a gestirle automaticamente
20. Gestione delle transazioni Analogamente ad ADO.NET, EntityFramework supporta la gestione delle transazioni in due modalità: Gestendo manualmente la connessione Utilizzando le classi del namespaceSystem.Transactions (ad esempio TransactionScope)
21. Gestione delle transazioni Gestione manuale delle connessioni entities.Connection.Open(); var transaction = entities.Connection.BeginTransaction(); try { Customers customer = new Customers(); customer.CustomerID = "KILOP"; customer.CompanyName = "Kilop"; entities.Customers.AddObject(customer); entities.Customers.DeleteObject(customer2); transaction.Commit(); } catch (Exception) { transaction.Rollback(); } finally { entities.Connection.Close(); }
22. Gestione delle transazioni Utilizzando System.Transactions using (TransactionScope scope = new TransactionScope()) { Customers customer = new Customers(); customer.CustomerID = "KILOP"; customer.CompanyName = "Kilop"; entities.Customers.AddObject(customer); entities.Customers.DeleteObject(customer2); entities.SaveChanges(); scope.Complete(); }
24. Lazyloading Utilizzando ADO.NETEntityFramework il risultato di una interrogazione è rappresentato da un oggetto o da una collezione Le relazioni tra le tabelle del database nel modello ad oggetti sono rappresentate da navigationproperty, cioè da proprietà delle classi che referenziano altri oggetti EntityFramework 4 introduce il concetto di LazyLoading: i dati di un oggetto relazionato vengono caricati solo se e quando viene richiamato il get della navigationproperty var customers = entities.Customers.Where(c => c.CustomerID == "ALFKI");var customerFound = customers.First();var orders = customerFound.Orders.ToList(); Lazyloading
26. POCO Normalmente Visual Studio a partire da un EDMX, genera una serie di classi che rappresentano le entità del modello concettuale Queste classe ereditano da EntityObject e sono oggetti piuttosto complessi: Numerosi attributi, partialmethod, INotifyPropertyChanged, ecc…. Utilizzare tali oggetti in tutta l’applicazione la rende fortemente dipendente dalla specifica tecnologia di accesso ai dati utilizzata e potrebbe non essere la soluzione ottimale quando si vogliono esporre servizi WCF Visual Studio 2010 e EntityFramework 4 introducono il supporto ai PlainOld CLR Object, cioè all’uso di classi semplici da utilizzare come modello concettuale Per implementare i POCO si adopera l’ADO.NETEntity POCO Generator