3. IntroduzioneUn framework di ObjectRelationalMapping (ORM) ha l’obiettivo di avvicinare la logica di interfacciamento alle basi di dati, alla logica della programmazione orientata agli oggettiVantaggiConsente di colmare il gap che esiste tra il modello relazionale ed il modello objectorientedRiduce drasticamente il codice scritto per interfacciarsi ai databasePermette di rendere lo strato di accesso ai dati indipendente dallo specifico RDBMS utilizzatoFavorisce lo spostamento della logica applicativa dalle stored procedure al codice
4. IntroduzioneA cosa serve quindi un ORM ? select (select max(answer.answer) from answer where answer.member_id in (select member_id from team_members where project_id in ( select project_id from project where Business_stream='Upstream' and stage='Appraise' and project_id in (select project_id from projectextra where subteam<>1 ) ) ) and answer.page_id=page.page_id) as thinl, (select max(avgscore) from task_projectwhere task_project.project_id not in (select project_id from projectextra where subteam=1 ) and task_project.project_id in (select project_id from project where stage='Appraise' and Business_stream = 'Upstream') and task_project.page_id=page.page_id) as bmax, (select max(answer) from answer where answer.page_id=page.page_id) as datamax, (select avg(avgscore) from task_project where project_id=1 and task_project.page_id=page.page_id) as projavg, (select avg(avgscore) from task_project where project_id not in (select project_id from projectextra where subteam=1) and task_project.page_id=page.page_id) as companyavg, (select avg(avgscore) from task_project where project_id not in (select project_id from projectextra where subteam=1) and project_id in (select project_id from project where Business_stream = 'Upstream') and task_project.page_id=page.page_id) as businessavg, page.* from page,riverorder where page.category_name='Business Boundaries' and stage_name='Appraise' and riverorder.category_name=page.category_name order by riverorder.riverorder,page.order_id select (select max(answer.answer) from answer where answer.member_id in ( select member_id from team_members where project_id in ( select project_id from project where Business_stream='Upstream' and stage='Appraise' and project_id in (select project_id from projectextra where subteam<>1 ) ) ) and answer.page_id=page.page_id) as thinl, (select max(avgscore) from task_project where task_project.project_id not in (select project_id from projectextra where subteam=1 ) and task_project.project_id in (select project_id from project where stage='Appraise' and Business_stream = 'Upstream') and task_project.page_id=page.page_id) as bmax, (select max(answer) from answer where answer.page_id=page.page_id) as datamax, (select avg(avgscore) from task_project where project_id=1 and task_project.page_id=page.page_id) as projavg, (select avg(avgscore) from task_project where project_id not in (select project_id from projectextra where subteam=1) and task_project.page_id=page.page_id) as companyavg, (select avg(avgscore) from task_project where project_id not in (select project_id from projectextra where subteam=1) and project_id in (select project_id from project where Business_stream = 'Upstream') and task_project.page_id=page.page_id) as businessavg, page.* from page,riverorder where page.category_name='Business Boundaries' and stage_name='Appraise' and riverorder.category_name=page.category_name order by riverorder.riverorder,page.order_id
5. IntroduzioneADO.NETEntityFramework è la proposta di Microsoft nel mercato degli ObjectRelational Mapper (ORM)StoriaV1 - .NET Framework 3.5 SP1V4 - .NET Framework 4
6. IntroduzioneADO.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 datiStore schema definitionlanguage (SSDL)Definisce lo schema di persistenza su database dei datiMappingspecificationlanguage (MSL)Definisce il mapping tra CSDL e SSDL
7. IntroduzioneE’ possibile generare l’Entity Data Model in tre modi:Database firstVisual 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 navigationpropertiesModel 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 databaseCode first (a partire da EntityFramework CTP 4)Si parte dalle classi del proprio modello
8. IntroduzioneArchitettura layeredObjectServicesForniscono l’accesso ai dati mediante l’ObjectContext e “contenitori di oggetti” denominati ObjectSetEntityClient Data ProviderGestisce le connessioni e converte le query dal modello concettuale al modello fisico utilizzando l’EDMADO.NET Data ProvidersEseguono l’accesso al database
9. IntroduzioneADO.NETEntityFramework è un’API indipendente dal database sottostanteUn database, per essere compatibile, deve fornire un provider ADO.NET in grado di supportare EntityFrameworkIl .NET Framework 3.5 SP1 o superiore integra un provider per l’accesso ai dati (SqlClient) compatibile con SQL Server 2000, 2005, 2008 e AzureEsistono provider (gratuiti o a pagamento) per tutti i più diffusi RDBMS: Oracle, MySql, PostgreSQL, DB2, SQLite, Sybase, ecc…
11. Operazioni sul databaseEntity SQLE’ il modo più prestante di eseguire interrogazioni mediante l’EntityFrameworkE’ un linguaggio SQL-like molto simile a T-SQL, usato per interrogare il modello concettualestring 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 databaseQueryMethodRappresentano una serie di metodi disponibili per l’ObjectSet che facilitano la costruzione di query rispetto all’uso diretto dell’Entity SQLE’ una soluzione che si pone in posizione intermedia tra LINQ e l’Entity SQLI metodi di query sono ottimizzati per introdurre un overhead minimo rispetto all’Entity SQLvar query = entities.Customers.Where("it.CustomerID = @id", new ObjectParameter("id", "ALFKI"));
13. Operazioni sul databaseLINQ toEntitiesPoiché gli ObjectSet implementano l’interfaccia IQuerable, possono essere interrogati utilizzando LINQ sia con la methodsyntax, che con la querysyntax//methodsyntaxvar customers = entities.Customers.Where(c => c.CustomerID == "ALFKI");//querysyntaxvarcustomers = fromcustomer in entities.Customerswherecustomer.CustomerID == “ALFKI” selectcustomer;
14. Operazioni sul databaseL’esecuzione delle interrogazioni su database viene effettivamente eseguita solo nei seguenti casi:Viene enumerato il risultato della queryViene applicato l’operatore First o Any con LINQLa query è, pertanto, eseguita solo quando i suoi risultati sono effettivamente necessarivar customers = entities.Customers.Where(c => c.CustomerID == "ALFKI");foreach (var customer in customersWithOrders) { … }Esecuzione query
16. Operazioni sul databaseCreateL’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 AddObjectDeleteAnalogamente all’operazione di inserimento, la cancellazione è supportata richiamando semplicemente il metodo DeleteObject dell’ObjectContextCustomers customer = new Customers();customer.CustomerID = "KILOP";customer.CompanyName = "Kilop";entities.Customers.AddObject(customer);entities.Customers.DeleteObject(customer);
17. Operazioni sul databaseUpdateNormalmente l’ObjectContext tiene traccia dello stato di tutti gli oggetti restituiti da una interrogazioneQuesta funzionalità gli consente di persistere su database le modifiche effettuate sulle proprietà degli oggettiPersistenzaLe operazioni di Insert, Update e Delete vengono persistite solo alla chiamata del metodo SaveChanges dell’ObjectContextIl metodo SaveChanges viene sempre eseguito in transazioneSe 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 connessioniADO.NETEntityFramework apre e chiude le connessioni automaticamente per il tempo strettamente necessario all’esecuzione di un’operazioneE’ 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 transazioniAnalogamente ad ADO.NET, EntityFramework supporta la gestione delle transazioni in due modalità:Gestendo manualmente la connessioneUtilizzando le classi del namespaceSystem.Transactions (ad esempio TransactionScope)
21. Gestione delle transazioniGestione 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 transazioniUtilizzando 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. LazyloadingUtilizzando ADO.NETEntityFramework il risultato di una interrogazione è rappresentato da un oggetto o da una collezioneLe relazioni tra le tabelle del database nel modello ad oggetti sono rappresentate da navigationproperty, cioè da proprietà delle classi che referenziano altri oggettiEntityFramework 4 introduce il concetto di LazyLoading: i dati di un oggetto relazionato vengono caricati solo se e quando viene richiamato il get della navigationpropertyvar customers = entities.Customers.Where(c => c.CustomerID == "ALFKI");var customerFound = customers.First();var orders = customerFound.Orders.ToList();Lazyloading
26. POCONormalmente Visual Studio a partire da un EDMX, genera una serie di classi che rappresentano le entità del modello concettualeQueste 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 WCFVisual Studio 2010 e EntityFramework 4 introducono il supporto ai PlainOld CLR Object, cioè all’uso di classi semplici da utilizzare come modello concettualePer implementare i POCO si adopera l’ADO.NETEntity POCO Generator