ADO.NET
Ottenere la flessibilità nella modellazione dati con Entity Framework
Elisa Flasko
In questo articolo verranno discussi i seguenti argomenti:
- La filosofia che supporta Entity Framework
- EDM (Entity Data Model)
- Interrogazione, associazione e sviluppo a n livelli
|
In questo articolo verranno utilizzate le seguenti tecnologie:
ADO.NET, LINQ, Entity Framework
|

Indice
ADO.NET Entity Framework sta per uscire! Introdotto per la prima volta come ADO.NET vNext nel 2006, il framework è ora pronto per il lancio con la prossima versione di Visual Studio® 2008 SP1. Dopo un paio di tentativi non corretti in prodotti simili negli ultimi anni, Microsoft ha rilasciato due tecnologie con Visual Studio 2008 che si adattavano, in parte, allo spazio ORM (Object Relational Mapping): LINQ to SQL e ADO.NET Entity Framework. Con l'adozione di tali tecnologie nel mercato, gli sviluppatori intendono ora sapere come si è arrivati fino a questo punto e quali sono i progetti futuri di Microsoft. Desiderano inoltre sapere quali sono gli elementi che supportano lo sviluppo di queste tecnologie, cosa rende Entity Framework diverso da altre tecnologie ORM nel mercato e in che modo Microsoft sta investendo in tali tecnologie per il futuro.
In seguito alla versione iniziale di Visual Studio 2008, sono stati scritti numerosi articoli incentrati su LINQ to SQL, oltre che articoli contenenti suggerimenti sulla tecnologia da utilizzare (consultare il sito all'indirizzo
msdn.microsoft.com/data) (in inglese). In questo articolo mi concentrerò su Entity Framework e fornirò indicazioni precise sulle modalità e sui motivi che hanno portato alle scelte eseguite durante lo sviluppo.
Microsoft® EDM (Entity Data Model), basato sul modello ER (Entity Relationship) del Dr. Peter Chen, è realmente la forza trainante di ADO.NET Entity Framework. EDM è anche la funzione che differenzia in modo più significativo Entity Framework da altre tecnologie in stile ORM nel mercato. EDM si basa sul modello ER per elevare il livello di astrazione per i modelli ad un ordine superiore rispetto ai modelli logici, preservando i concetti di entità e relazioni.
Perché un altro modello di dati?
Quindi, perché era necessario un altro modello? Con l'aumento dei dati gestiti dalle società, è diventato molto complicato comprendere e sviluppare applicazioni sulla base di tali dati. Gli schemi database sono concepiti tenendo presenti le questioni legate all'archiviazione, ovvero integrità dei dati, prestazioni e gestione e non sempre sono semplici da capire. Spesso tali schemi non sono in linea con la struttura della propria applicazione, il che complica ulteriormente lo sviluppo e la manutenzione.
Le soluzioni personalizzate in cui la struttura dei dati veniva separata dall'applicazione creata divennero comuni. Purtroppo, considerato il numero di soluzioni personalizzate, vari approcci e operazioni richieste per la modellazione dati, differenti per ogni applicazione, il problema è diventato ancora più importante. Nel settore vi era un'esigenza costante di definizione e sviluppo rispetto ad un modello di dominio a livello di applicazione, che potesse essere separato in modo chiaro dal modello logico dell'archivio. Esaminiamo Entity Framework.
EDM (vedere l'esempio mostrato nella Figura 1) consente la definizione di un modello di dominio congruente con la modalità tramite cui un'organizzazione pensa e utilizza i propri dati, anziché con la modalità di archiviazione di tali dati da parte della stessa organizzazione. EDM è stato inoltre sviluppato con l'obiettivo primario di divenire il modello di dati principale in una suite di tecnologie per server e sviluppatore all'interno di Microsoft.
Figura 1 EDM (Entity Data Model) di esempio per un database di gestione blog (fare clic sull'immagine per ingrandirla)
Con un modello di dati principale, la gestione dell'applicazione risulta semplificata. Quando viene realizzato tale obiettivo, EDM può essere utilizzato per definire un modello non solo per applicazioni personalizzate create su ADO.NET Entity Framework ma anche come input per applicazioni di creazione di report e di visualizzazione, applicazioni di portali intranet o del flusso di lavoro.
In modo simile al modello ER, EDM utilizza due concetti primari: entità (oggetti) e relazioni (o associazioni) tra tali entità. Quando si ha a che fare con l'archiviazione di istanze di entità e di associazione o con la chiusura di operazioni di impostazione su tali istanze, il concetto di serie è obbligatorio. Di conseguenza, per completare il quadro, le entità risiedono in EntitySet e le associazioni risiedono in AssociationSet.
Il concetto strutturale finale definito in EDM è quello di un EntityContainer, che definisce una chiusura intorno alle serie di istanze e relazioni precedentemente descritte. Questi semplici concetti, utilizzati insieme, consentono agli sviluppatori di definire un modello di dominio da associare al livello di persistenza e alle classi utilizzate nell'applicazione stessa. Tenere presente che non è necessario che il livello di persistenza di EDM sia relazionale, anche se attualmente lo è.
Ogni tipo di entità definito in un EDM può contenere due tipi diversi di membri: proprietà che definiscono l'entità (analoghe alle colonne nel database) e proprietà di navigazione, che consentono l'esplorazione di relazioni a cui partecipa il tipo di entità, spesso rappresentate come chiavi esterne nel database). Oltre a questi elementi, ogni tipo di entità deve disporre di una chiave o identità distinta. Il frammento XML nella Figura 2 descrive un tipo di entità "Blog Post".

Figura 2 Definizione del tipo di entità BlogPost
<EntityType Name="BlogPost">
<Key>
<PropertyRef Name="BlogPostID" />
</Key>
<Property Name="BlogPostID" Type="Int32" Nullable="false" />
<Property Name="BlogEntry" Type="String" Nullable="false" MaxLength="Max"
Unicode="true" FixedLength="false" />
<Property Name="BlogDate" Type="DateTime" Nullable="false" />
<Property Name="BlogTitle" Type="String" Nullable="false" MaxLength="500"
Unicode="true" FixedLength="false" />
<Property Name="BlogType" Type="Int32" Nullable="false" />
<Property Name="CityVisited" Type="String" MaxLength="200"
Unicode="true" FixedLength="false" />
<Property Name="CountryVisited" Type="String" MaxLength="200" Unicode="true"
FixedLength="false" />
<Property Name="DateVisited" Type="DateTime" />
<NavigationProperty Name="Blog" Relationship=
"MyTravelPostModel.FK_BlogPosts_Blogs"
FromRole="BlogPosts" ToRole="Blogs" />
<NavigationProperty Name="Pictures" Relationship=
"MyTravelPostModel.FK_Pictures_BlogPosts"
FromRole="BlogPosts" ToRole="Pictures" />
<NavigationProperty Name="Comments" Relationship=
"MyTravelPostModel.BlogComments"
FromRole="BlogPosts" ToRole="Comments" />
</EntityType>
Le proprietà su un tipo di entità possono essere tipi primitivi o complessi (vedere la Figura 3), ma in Entity Framework 1.0 non possono essere altri tipi di entità o raccolte di tipi complessi o primitivi. La chiave del tipo di entità è quindi composta da una sottoserie di tali proprietà. Le proprietà di esplorazione consentono l'esplorazione di una relazione da un'entità ad un'altra.

Figura 3 Tipo complesso AddressType
<ComplexType Name="Address">
<Property Name="StreetAddress"
Type="String" MaxLength="50" />
<Property Name="Address2"
Type="String" MaxLength="50" />
<Property Name="City"
Type="String" MaxLength="50" />
<Property Name="Region"
Type="String" MaxLength="50" />
<Property Name="PostalCode"
Type="String" MaxLength="50" />
<Property Name="Country"
Type="String" MaxLength="50" />
</ComplexType>
Come discusso in precedenza, le relazioni possono essere replicate come proprietà di esplorazione su ogni tipo di entità che fa parte della relazione. Le relazioni stesse si sono conquistate un posto di primo piano all'interno di EDM e sono definite esplicitamente come associazioni all'interno di EDM:
<Association Name="FK_Friends_People">
<End Role="People" Type="MyTravelPostModel.Person" Multiplicity="1" />
<End Role="Friends" Type="MyTravelPostModel.Friend" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="People">
<PropertyRef Name="PersonID" />
</Principal>
<Dependent Role="Friends">
<PropertyRef Name="PrimaryPersonID" />
</Dependent>
</ReferentialConstraint>
</Association>
Quindi, in breve, perché allora abbiamo creato una nuova tecnologia di modellazione dati? Sebbene prima di EDM esistessero alcuni linguaggi o tecnologie di modellazione dati, nessuno era in grado di soddisfare gli obiettivi primari che Microsoft stava tentando di portare a compimento e nessuno serviva a rendere eseguibile il modello Entity Relationship così diffuso. Il team ha analizzato numerose tecnologie di modellazione dati ma, rendendosi conto che erano tutte praticamente specifiche o incentrate su alcune aree di problemi, ha iniziato a sviluppare EDM per creare un modello che soddisfacesse tali obiettivi e che potesse essere realmente utilizzato come modello di dati principale in una suite di tecnologie per sviluppatori e server.
Perché descrivere EDM con XML?
Dopo un attento esame, XML è stato scelto come la prima rappresentazione seriale per EDM. La presenza di un formato XML ben definito consente a sviluppatori e terze parti di eseguire delle conversioni in tale formato e di effettuare il caricamento nel runtime dei metadati di Entity Framework, generando file o risorse XML o caricandoli da rappresentazioni XML generate in modo dinamico. È plausibile, tuttavia, che sia possibile creare altre rappresentazioni di EDM ed è probabile che le rappresentazioni alternative compariranno con l'uscita delle future versioni del prodotto.
La grammatica corrente di EDM è definita in un linguaggio XSD (XML Schema Definition) fornito con il prodotto. Non ci si aspetta, tuttavia, che la maggior parte delle persone svilupperanno l'XML manualmente, ma utilizzeranno piuttosto gli strumenti forniti in Visual Studio. Premesso ciò, il team ha notato l'interesse in DSL (Domain-Specific Language) e in meccanismi di persistenza alternativi (tra cui i database, che sono i più comuni) per modelli EDM e sta valutando le opzioni per l'espansione nelle versioni imminenti.
Chi ha bisogno di un altro nuovo linguaggio di query?
L'ultima domanda correlata allo sviluppo di EDM è: perché creare un nuovo linguaggio di query? Perché non utilizzarne uno esistente? La risposta apparirà più chiara dopo che avrò illustrato con maggiori dettagli EDM.
Finora ho spiegato i motivi che hanno portato alla creazione di EDM e descritto i vari costrutti utilizzati al suo interno, sottolineando la discendenza del modello dal modello Entity Relationship. Nella creazione di un modello che fosse in grado non solo di associare chiaramente l'archivio dati sottostante, ma di rappresentare il modello di dominio a livello di applicazione rispetto a cui gli sviluppatori avrebbero voluto eseguire una programmazione, EDM doveva consentire la modellazione di concetti quali l'ereditarietà e il polimorfismo. Poiché i linguaggi di query relazionali correnti non supportano l'esecuzione di query in base all'ereditarietà, all'esplorazione delle relazioni o alla restituzione di risultati polimorfici, era necessario un nuovo linguaggio di query che soddisfacesse tale requisito.
Fu così che ebbe origine ESQL (Entity SQL), un nuovo dialetto SQL che consente di eseguire una query in base ai concetti non supportati in precedenti dialetti SQL. ESQL estende il linguaggio SQL esistente nello stesso modo in cui EDM estende il modello relazionale utilizzato nei database. Inoltre, ESQL non è legato alla sintassi di specifici database back-end e consente di scrivere una sola volta le query e/o l'applicazione, indipendentemente dal database back-end utilizzato come destinazione. Nel seguente esempio, esamino una semplice query ESQL che richiamerà tutti i blog contenenti almeno un post e la persona (o, nel caso del mio modello, il proprietario del blog) associata:
select c, c.Person
from travelEntitiesGeneral.Blogs as c
where c.BlogPosts.Count > 0
Implementazione di EDM
ADO.NET Entity Framework è un'evoluzione di ADO.NET e la prima implementazione concreta di EDM, che fornisce un livello di astrazione più elevato in caso di sviluppo rispetto ad un database relazionale. Nella versione 1.0, il team si è concentrato sulla creazione delle basi di una piattaforma, più che un semplice ORM, che consentirà agli sviluppatori di lavorare con un modello concettuale o di oggetto con un'associazione estremamente flessibile e con la possibilità di raggiungere un elevato grado di divergenza dall'archivio sottostante.
Tale grado elevato di flessibilità e divergenza dall'archivio sottostante è la chiave per consentire l'evoluzione separata di database e applicazioni. Quando si apporta una modifica nello schema del database, l'applicazione viene isolata dalla modifica tramite Entity Framework e, generalmente, non viene richiesto di riscrivere parti dell'applicazione ma piuttosto di aggiornare i file di associazione, se necessario, per applicare la modifica.
Per iniziare l'evoluzione della piattaforma ADO.NET, Entity Framework si basa sul modello di provider ADO.NET 2.0 esistente, con i provider esistenti aggiornati per supportare la nuova funzionalità di Entity Framework e ADO.NET 3.5. Abbiamo scelto di eseguire un'implementazione basandoci sul modello di provider ADO.NET esistente per garantire un modello di provider che fosse familiare per la comunità di sviluppo.
L'architettura è illustrata nella Figura 4. Si noterà che gli schemi consentiti includono CSDL (Conceptual Schema Definition Language), MSL (Mapping Schema Language) e SSDL (Storage Schema Definition Language). Inoltre, Entity Framework include un provider di dati SqlClient aggiornato che supporta CCT (canonical command tree).
Figura 4 Architettura di ADO.NET Entity Framework (fare clic sull'immagine per ingrandirla)
EntityClient
Entity Framework introduce quindi un nuovo provider ADO.NET, EntityClient, basato su tali provider ADO.NET 3.5. EntityClient è molto simile ai provider ADO.NET comuni e fornisce la prima astrazione che consente agli sviluppatori di eseguire delle query in termini di EDM, utilizzando gli oggetti standard Connection, Command e DataReader. Aggiunge inoltre il Motore delle viste client aggiuntivo necessario per associare il modello di dominio, definito in termini di EDM, allo schema di database relazionale sottostante. EntityClient consente agli sviluppatori, laddove necessario, di lavorare con entità nel formato di righe e colonne tramite stringhe di query ESQL senza necessità di generare delle classi per rappresentare lo schema concettuale.
Se esaminate l'uso di EntityClient nella Figura 5, noterete che ho creato un EntityCommand che include una stringa di query ESQL e che tale comando viene quindi eseguito rispetto al mio EDM. Il testo di query fornito come parte di EntityCommand viene analizzato e viene creato un CCT.

Figura 5 Uso di ESQL per eseguire una query di EntityClient
using (EntityConnection conn = new
EntityConnection("name=travelEntitiesGeneral"))
{
conn.Open();
EntityCommand cmd = conn.CreateCommand();
cmd.CommandText = @"select c.BlogID
from travelEntitiesGeneral.Blogs as c
where c.BlogPosts.Count > 0";
EntityDataReader reader =
cmd.ExecuteReader(CommandBehavior.SequentialAccess);
while (reader.Read())
{
Console.WriteLine("BlogID = {0}", reader["BlogID"]);
}
conn.Close();
}
Nella prima fase, la struttura di comandi è ancora rappresentata in termini di EDM. Il Motore delle viste client, prendendo in prestito le teorie per le viste materializzate nei sistemi database ma applicando tali teorie al livello di accesso ai dati, applica una conversione di associazione alla struttura ad albero, producendone un'altra che rappresenta la stessa operazione in termini del modello di archiviazione logica sottostante e rimuovendo qualsiasi concetto non relazionale come, ad esempio, relazioni, ereditarietà e polimorfismo. Tale struttura appena convertita viene gestita nei servizi del provider ADO.NET 3.5, che restituisce un DbCommand che incapsula un SQL nativo per l'archivio sottostante, che viene quindi eseguito e i cui risultati vengono propagati come backup tramite lo stack.
Quando si definisce l'associazione utilizzata nel Motore delle viste client per eseguire una conversione tra EDM e lo schema database logico, sono disponibili un paio di opzioni differenti. L'associazione può essere specificata utilizzando una grammatica XML dichiarativa, ovvero MSL (Mapping Specification Language) che è possibile creare e modificare tramite codifica manuale dell'XML o utilizzando gli strumenti di associazione identità inclusi in Visual Studio (vedere la Figura 6).

Figura 6 MSL: esempio EntitySetMapping
<EntitySetMapping Name="BlogPosts">
<EntityTypeMapping TypeName="IsTypeOf(MyTravelPostModel.BlogPost)">
<MappingFragment StoreEntitySet="BlogPosts">
<ScalarProperty Name="BlogPostID" ColumnName="BlogPostID" />
<ScalarProperty Name="BlogEntry" ColumnName="BlogEntry" />
<ScalarProperty Name="BlogDate" ColumnName="BlogDate" />
<ScalarProperty Name="BlogTitle" ColumnName="BlogTitle" />
<ScalarProperty Name="BlogType" ColumnName="BlogType" />
<ScalarProperty Name="CityVisited" ColumnName="CityVisited" />
<ScalarProperty Name="CountryVisited"
ColumnName="CountryVisited" />
<ScalarProperty Name="DateVisited" ColumnName="DateVisited" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
Una volta compilato, MSL consente ad Entity Framework di generare la query necessaria e di aggiornare le viste che vengono poi utilizzate all'interno del Motore delle viste client per ottenere la conversione della query definita in termini di EDM nello schema di archiviazione logico.
Un'opzione alternativa per esprimere l'associazione o parte di essa prevede l'utilizzo di una query ESQL. In questo caso, quando lo sviluppatore esprima la vista query tramite ESQL, l'infrastruttura richiede anche la definizione delle associazioni Create, Update e Delete nella relativa specifica. Tale operazione è necessaria poiché l'infrastruttura di associazione non è in grado di generare una vista di aggiornamento corrispondente per la vista query considerato che una può sfruttare la potenza di ESQL nella vista query, rendendo possibile la presenza di viste definite per cui non esiste una singola vista di aggiornamento valida.
Object Services
Sulla base del provider EntityClient, Entity Framework aggiunge un'altra serie di astrazioni per consentire lo sviluppo rispetto ad oggetti anziché record di dati non tipizzati restituiti da EntityClient. Questo è il livello maggiormente indicato come ORM, che produce istanze CLR dei tipi definiti in un modello di dati e che consente agli sviluppatori di eseguire query rispetto a tali oggetti utilizzando LINQ o ESQL. Questo è anche il livello di Entity Framework responsabile dell'avvicinamento iniziale di molti sviluppatori alla tecnologia quando si esaminano le tecnologie ORM disponibili, presenti sul mercato.
Come avrete notato nella Figura 1, la funzione di alto livello del livello Object Services consiste nell'inclusione di query ESQL o LINQ dall'applicazione, nell'inoltro di un'espressione di query all'EntityClient riportato di seguito e nella restituzione di IEnumerable<T>. Per esaminare la questione in maniera più approfondita, tuttavia, il cuore del livello Object Services è ObjectContext, che rappresenta la sessione di interazione tra l'applicazione e l'archivio dati sottostante.
ObjectContext è il costrutto primario gestito dallo sviluppatore per eseguire query, aggiungere ed eliminare istanze di entità e per salvare il nuovo stato nel database. La creazione e l'uso di ObjectContext per eseguire query, modificare e utilizzare il metodo SaveChanges per un'entità vengono mostrati nella Figura 7. In questo esempio si utilizza ESQL come linguaggio di query.

Figura 7 Utilizzo di ObjectContext
using (ObjectContext context = new ObjectContext("name=travelEntities"))
{
//--- create a query for customers
ObjectQuery<Person> personQuery = context.CreateQuery<Person>(
@"select value c from travelEntitiesGeneral.People
as c where c.PersonID == 1");
//--- by enumerating the query will be implicitly executed
//--- against the store and you can now work with an
//--- IEnumerable<Customer>
foreach (Person c in personQuery)
{
//--- dereference anything you like from Customer
Console.WriteLine(c.PersonID + ": " + c.Name);
c.Name = "New Name";
}
try
{
context.SaveChanges();
}
catch (OptimisticConcurrencyException opt)
{
// catching this exception allows you to
// refresh travelEntities with either store/client wins
// project the travelEntities into this failed travelEntities.
var failedEntities = from e3 in opt.StateEntries
select new { e3.Entity };
// Note: in future you should be able to just pass
// the opt.StateEntities
// in to refresh.
context.Refresh(RefreshMode.ClientWins, failedEntities.ToList());
context.SaveChanges();
}
}
Il processo di gestione delle modifiche non appena vengono eseguite agli oggetti in memoria e il processo di salvataggio di tali modifiche nel database è semplificato per lo sviluppatore grazie all'uso di Object Services. Object Services utilizza ObjectStateManager per tenere traccia non solo dello stato corrente delle istanze in memoria, ma anche dello stato iniziale di ogni istanza richiamata dall'archivio, consentendo ad Entity Framework di applicare una concorrenza ottimistica durante l'inserimento dei dati nel database. Le modifiche registrate vengono salvate e restituite all'archivio dati senza problemi, con il richiamo del metodo SaveChanges su ObjectContext.
Finora ho parlato di ObjectContext in generale e, nei miei esempi, ho mostrato l'uso di un ObjectContext di base, generalmente utilizzato nello scenario in cui è presente un'applicazione o strumento dinamico che utilizza modelli EDM. Quando si utilizza Visual Studio come ambiente di sviluppo, tuttavia, gli sviluppatori prediligono un ObjectContext fortemente tipizzato, aggiungendo proprietà e metodi a capacità superficiali che potrebbero essere specifiche dell'EDM scelto come destinazione.
Nella Figura 8 viene mostrata una query creata tramite un ObjectContext fortemente tipizzato. In questo esempio si dimostra l'uso di LINQ come linguaggio di query. L'utilizzo di un ObjectContext fortemente tipizzato espone delle proprietà per ogni EntitySet, rendendoli più individuabili; ad esempio, travelEntities.BlogPosts anziché travelEntities.CreateQuery<BlogPost>("travelEntitiesGeneral.BlogPosts").

Figura 8 Query creata tramite un ObjectContext fortemente tipizzato
using (MyTravelPostEntities travelEntities = new MyTravelPostEntities())
{
// get the latest blog post, with the comments and the people
// I'm querying for all the blog posts that are related to this blog.
// I want to include the comments and the people who wrote the
// comments.
// I also want only the most recent posting.
// Note: Since we use the EntityKey that is put on the EntityReference
// we can either do a tracking query or use span.
BlogPost post = (from bp in
travelEntities.BlogPosts
.Include("Comments.Person")
.Include("Blog")
where bp.Blog.BlogID == requestedBlog.BlogID
orderby bp.BlogDate descending
select bp).First();
return post;
}
LINQ to Entities è una sorta di livello ridotto su Object Services, che fornisce funzionalità di query direttamente all'interno del linguaggio di programmazione (vedere la Figura 8) rispetto ad una query basata su stringhe. In questo caso, la classe ObjectQuery implementa IQueryable, consentendo l'inserimento di una struttura di espressioni LINQ al suo interno, inoltrando la query tramite Entity Framework come espressione di query CCT nello stesso modo in cui Object Services inoltrerebbe una query ESQL al provider EntityClient.
Sviluppo a n livelli con Entity Framework
Sebbene il mio obiettivo primario non sia quello di soffermarmi su uno sviluppo a n livelli, dal momento che è uno degli scenari più interessanti per lo sviluppo con Entity Framework, merita di essere per lo meno illustrato. Nella versione 1.0, Entity Framework supporta uno sviluppo a n livelli in un paio di scenari primari. Tali scenari includono l'uso di ADO.NET Data Services o l'uso di WCF (Windows® Communication Foundation) con la capacità di serializzare le entità e di dissociarle da un ObjectContext. Ovviamente questi non sono gli unici approcci ad uno sviluppo a n livelli; tuttavia, sono le soluzioni su cui il team ha scelto di concentrarsi nella V1, aggiungendo ulteriori scenari a partire dalla V2, tra cui un'esperienza più simile ai dataset. La Figura 9 dimostra i concetti di cui sto parlando.

Figura 9 ADO.NET Data Services in applicazioni a n livelli
static Uri baseService = new
Uri("http://localhost:17338/MyTravelPostService.svc");
MyPeople2Entities context = new MyPeople2Entities(baseService);
// get the comment that is being marked for deletion
// and get the view state blog post.
BlogPost post = (BlogPost)ViewState["BlogPost"];
// move the comment to the deleted comment selection.
Comment deletedComment = post.Comments[e.RowIndex];
// call the DeleteComment service
context.AttachTo("Comments", deletedComment);
context.DeleteObject(deletedComment);
DataServiceResponse r = context.SaveChanges();
// reload page so that F5, refresh doesn't update all this data.
ReloadPage();
ADO.NET Data Services è una realizzazione concreta di uno stile di architettura REST (Representational State Transfer) in cui ogni risorsa rappresenta un sostantivo nel sistema (situazione che è possibile affrontare in modo univoco tramite un URI o Uniform Resource Identifier), che consente lo sviluppo di un'applicazione a n livello su qualsiasi implementazione arbitraria di IQueryable. Con ADO.NET Data Services, è possibile andare oltre l'esecuzione di query per istanze tramite connessione. ADO.NET Data Services supporta i vari verbi HTTP per Create, Read, Update e Delete e fornisce astrazioni lato client per consentire agli sviluppatori di implementare le proprie soluzioni.
La seconda opzione per scenari a n livelli è l'uso di WCF con Entity Framework, che usufruisce della possibilità di serializzazione delle entità e di associazione e dissociazione di tali entità da ObjectContext. Nella Figura 10 viene mostrato come stabilire un'associazione con ObjectContext in questo scenario.

Figura 10 Associazione ad ObjectContext
// the creation of the travel MyTravelPostEntities opens the connection
// and sets up all the metadata information automatically for you.
using (MyTravelPostEntities travelEntities = new MyTravelPostEntities())
{
// attach the comment and delete.
travelEntities.Attach(deleteComment);
// call delete on the object
travelEntities.DeleteObject(deleteComment);
try
{
travelEntities.SaveChanges();
}
catch (OptimisticConcurrencyException opt)
{
// catching this exception allows you to
// refresh travelEntities with either store/client wins
// project the travelEntities into this failed travelEntities.
var failedEntities = from e3 in opt.StateEntries
select new { e3.Entity };
travelEntities.Refresh(RefreshMode.ClientWins, failedEntities.ToList());
travelEntities.SaveChanges();
}
}
Per impostazione predefinita, le classi CLR generate da EDM in Visual Studio o che utilizzano edmgen.exe (lo strumento della riga comandi fornito con Entity Framework) sono serializzabili in formato XML e binario e sono contratti di dati con proprietà di esplorazione attribuite come DataMember per impostazione predefinita, il che rende possibile creare ASMX Web services e utilizzare istanze di entità in servizi WCF o nello stato di visualizzazione.
Come la maggior parte degli ORM, attualmente Entity Framework non supporta operazioni DML (Data Manipulation Language) per la creazione l'aggiornamento o l'eliminazione. Le modifiche devono essere applicate agli oggetti in memoria e la creazione dell'intero grafico da rendere persistente potrebbe richiedere diversi cicli di richiesta/risposta al database.
Un modo per evitare tale situazione consiste nell'utilizzo della funzionalità attach offerta da ObjectContext. L'utilizzo di Attach consente di specificare nell'infrastruttura la presenza dell'entità e di richiedere l'esecuzione di una serie di operazioni in memoria e l'inserimento delle modifiche. Per ulteriori informazioni sullo sviluppo a n livelli con Entity Framework, consultare la MSDN® Library, poiché presto verranno aggiunti nuovi contenuti.
Un altro ORM?
Finora, Entity Framework è stato considerato da molti un altro ORM presente sul mercato, il che è comprensibile se si esamina soltanto la prima versione del prodotto. In tale direzione, molti degli elementi inclusi nel prodotto finora consentono una serie principale di scenari che ORM sta iniziando a supportare. Gran parte dell'analisi condotta finora, tuttavia, ha evidenziato che Entity Framework non offre sempre ciò che ci si aspetta dagli altri ORM presenti sul mercato e questa è una valida osservazione.
L'investimento di Microsoft in questo spazio è concepito per andare al di là un tradizionale prodotto ORM ed Entity Framework, come illustrerò tra breve, è una strategia molto più ampia relativa ad EDM. EDM, come ho sottolineato all'inizio di questo articolo, crea un modello di dominio di livello più elevato che sarà applicabile al di là di Entity Framework e del mondo di ORM tradizionali. L'aspettativa è che, con le prossime versioni di Microsoft .NET Framework, Visual Studio, SQL Server® e altre tecnologie Microsoft, l'utilizzo di EDM inizierà ad aumentare.
Tale aspettativa e la visione generale del futuro di EDM sono state l'influenza primaria per tale situazione, come dimostrato in molte delle decisioni relative al prodotto, discusse nel presente articolo. Molte di tali decisioni sono state prese con l'intento esplicito di consentire l'adozione da parte di tecnologie quali, ad esempio Reporting Services e Analysis Services. Questa operazione porterà un notevole vantaggio ai clienti, poiché i servizi potranno essere offerti su un modello di dominio comune e congruente.
La prima realizzazione di tale visione avverrà con Entity Framework in Visual Studio 2008 SP1 come ADO.NET Data Services. ADO.NET Data Services, che offre un'esperienza eccellente per gli sviluppatori per applicazioni basate su REST, sarà il primo prodotto rilasciato (al di là di Entity Framework) ad essere creato con EDM come formato per lo scambio di metadati.
In combinazione con tale versione e in occasione dell'evento MIX 2008, Microsoft ha illustrato numerose proprietà Windows Live™ differenti che espongono i relativi dati tramite il protocollo ADO.NET Data Services ed EDM. In modo analogo, mentre è in corso la pianificazione per la versione successiva di SQL Server e Visual Studio, il team sta lavorando sodo su migliori esperienze di sviluppo end-to-end con EDM ed Entity Framework come elementi centrali.