Udostępnij za pośrednictwem


LINQ, LINQ to SQL e ADO.NET Entity Framework

Si è appena concluso l'evento di Lancio a Perugia con i ragazzi di .NetUmbria, grazie a  tutti per i feedback ricevuti, ecco un breve sunto della sessione, con qualche link utile ...spero.

LINQ to *

Una delle novità più impotanti di .NET Framework 3.5 è sicuramente LINQ. Con Language Integrated Query abbiamo a disposizione una "sintassi alla SQL" per accedere a diverse sorgenti dati: collezioni di oggetti, nodi XML, DataSet e SQL Server, permettendo di lavorare utilizzando un approccio dichiarativo invece che imperativo. Questo ci consente di esprime ciò che vogliamo nel nostro codice in modo più semplice e leggibile, in molte situazioni.

La mia presentazione non è stata proprio introduttiva sull'argomento e per chi vuole saperne di più sulle novità ai Linguaggi C# 3.0, VB 9, o vuole avere una panoramica un po' più ampia sull'argomento consiglio di iniziare da questo tutorial scaricabile su LINQ e le novità dei linguaggi .NET.  Durante la sessione mi sono concentrato di più su LINQ to SQL e ho introdotto l'ADO.NET Entity Framework cercando di chiarirne gli obbiettivi e di metterne in eveidenza le potenzialità d'utilizzo, nonchè di far capire che relazione esiste con LINQ to Entities.

LINQ to SQL

Linq to SQL è l' implementazione LINQ per SQL Server, e solo per SQL Server. E' possibile utilizzare LINQ sia per interrogare SQL Server che per effettuare operazioni di aggiornamento/inserimento e modifica. Il linguaggio usato da LINQ to SQL è sicuramente molto espressivo, tanto che non è possibile avere una query T-SQL non esprimibile con LINQ to SQL. Per essere ancora più chiari, tenete presente che le query generate dall'engine sono state fatte dal team di prodotto di SQL Server.  Da un certo punto di vista LINQ to SQL è anche più potente del T-SQL, permettendo di scrivere  query come quella mostrata nell' esempio:

image

In cui possiamo chiedere la lista di clienti della città London e, tra questi, solo quelli che hanno un numero di ordini superiori a 4. Nel tipo anonimo ritornato una delle due proprietà è una lista di particolari ordini per quel cliente. Questa query LINQ, tutto sommato comprensibile, genera del codice SQL più complesso, con tanto di LEFT OUTER JOIN.

image

LINQ to SQL e Store Procedure - Insert/Update/Delete

Una delle domande che più spesso ricevo è se si possono usare le store procedure con LINQ to SQL. La risposta è sì e con pieno supporto del designer. Ad esempio posso modificare il comportamento di quello che viene definito come "Behaviour" delle classi generate per fare in modo di andare ad inserire le mie logiche di Insert/Update/Delete. Nell'immagine vedete come selezionare una classe generata dal Designer di Visual Studio e come sia possibile mappare sull'operazione di Update di LINQ to SQL il comportamento di una Store Procedure. Prima dobbiamo avere associato (facendo drag-&-drop) delle store procedure al designer di Visual Studio (nel mio caso la StoreProcedure UpdateOrder): questo genera dietro le quinte il codice necessario per eseguire la chiamata alla store procedure.

E' da notare che il modificare il comportamento di LINQ to SQL per dirgli di utilizzare una store procedure per effettuare un'operazione di update non ha impatto sul codice che scriveremmo nell'applicazione per creare un ordine, aggiungere l'ordine alla collezione degli ordini del cliente e così via: ho omesso questo codice nelle figure seguenti, dove si vedere solo come dire alle classi di LINQ to SQL di utilizzare una store procedure invece di utilizzare il codice generato dal run-time stesso. Spero di essere stato sufficentemente chiaro.

image

image

LINQ to SQL  Store Precedure & TVF

E se ho una store procedure che recupera dati, anzichè fare insert/update o delete ? Certo la posso utilizzare ad  esempio posso richiamare una store procedure che recupera i clienti per città e utilizzarla dalla classe DataContext specializzata. Quindi posso scrivere:

image

Dove db è sempre il Data Context specializzato, mentre il metodo va a richiamare una store procedure su database.

Ora, dato che la store procedure recupera una lista di clienti, mi potrebbe venire in mente di effettuare un'operazione di filtraggio (con una where) sul risultato. Quello che succede è che il filtraggio viene però eseguito in memoria, cioè se scrivo:

image

Quello che vediamo su SQL Server è solo l'esecuzione della store procedure, il risultato del nostro codice è però quello atteso: non solo ho clienti della città prescelta, ma ho filtrato in base a quelli il cui contactname inizia per "B", operazione quest'ultima effettuata in memoria.

LINQ to SQL supporta anche l'uso delle Table-Value Function (TVF), che, grazie alla loro componibilità, offrono invece un meccanismo diverso. Avendo una TVF nel db che fa le stesse operazioni che fa la store procedure, questa volta se richiamo la mia TVF e filtro come in precedenza:

image

Notate che nell'ultimo esempio sto chiamando un metodo diverso dal precedente, che appunto si mappa su una TVF su db.Questa volta il codice che viene eseguito su SQL Server contiene anche l'operazione di filtraggio, come vedete nella seguente immagine in cui viene appunto mostrato il codice SQL che SQL Server genera

image 

ADO.NET Entity Framework (EF) e LINQ to Entities

Nella presentazione ho anche introdotto l' ADO.NET Entity Framework (EF). Ci tengo a ricordare che EF e Linq To Entities non sono stati rilasciati con Visual Studio, ma sono in beta attualmente.

L'idea di base di EF è di aumentare il livello di astrazione con cui lavoriamo nelle applicazioni. Cioè possiamo modellare delle classi che non si mappano a priori in modo diretto su una tabella di un database. Ad esempio la mia entità customer può poi mapparsi su n tabelle del mio database. Un' altra importante caratteristica di EF è che è pensato per poter essere utilizzato con diversi database. Nella slide seguente trovate l'architettura di EF in cui si evincono almeno le seguenti caratteristiche:

  • è stato implementato un nuvo provider EntityClient che si appoggia sul meccanismo a provider di ADO.NET 2.0
  • per "parlare" con EF  esiste un linguaggio  Entity SQL, che è espresso per mezzo di una stringa, ma che mi permette di lavorare con Entità e non con tabelle.
  • LINQ to Entities è una implementazione di LINQ per lavorare con EF (sia lettura, che scrittura)

image

Ok, lungi dal voler essere completo in questo post qui trovate descritto l'esempio della sessione in cui potete vedere come ho modelli ad oggetti diversi se lavoro con LINQ to SQL rispetto a se lavoro con LINQ to Entities su un database comune di riferimento.

Quando usare LINQ to SQL e quando usare LINQ to Entities ?

LINQ to SQL è pensato per essere il modo più rapido per accedere a SQL Server e in scenari in cui il nostro modello ad oggetti si mappa 1:1 con le tabelle del nostro database. LINQ to Entities è pensato per scenari in cui le il database evolve in modo indipendente dal modello ad oggetti e dove non c'è necessariamente mappaggio uno-a-uno. Con EF posso esprimere nel  mio modello ad oggetti, da cui posso partire nella progettazione, relazioni molti-a-molti, come ad esempio quella tra Autori e Libri. L'architettura di EF inoltre consente di aggiungere provider per altri fornitori di DBMS. Esistono altre caratteristiche di differenziazioni e vi consiglio di leggere questo articolo per una trattazione completa.

Potete vedere le slide della sessione da SlideShare qui.

SlideShare | View | Upload your own

Spero che la presentazione vi sia stata utile e grazie a tutti per la numerosa partecipazione.

Penso che a breve potrete trovare sul sito di .NetUmbria un reportage fotografico della splendida giornata, nonchè il matereriale delle altre presentazioni ...

Comments

  • Anonymous
    May 26, 2008
    Pietro, non so se la domanda e’ di carattere generale e magari interessa anche ad altri, ma vorrei capire se e’ possibile usare LINQ to SQL per fare una query su una tabella facendosi restituire i valori solo di alcune colonne, ma mantenendo lo stesso oggetto che si ottiene con la query completa. Chiaramente la query e’ in modalita’ read-only, nel senso che poi quei dati non vengono usati per un aggiornamento.

  • Anonymous
    May 26, 2008
    Ciao Enrico, in effetti è così: il designer di vs 08 crea un classe per ogni tabella sul db. Ogni colonna è mappata su una colonna. Quando poi usi linq to sql per fare la query puoi decidere le proprietà della classe ( e quindi quale colonna della tabella) che verrà restituita. Certo, la query è in modalità read-only, ma puoi modificare gli oggetti che hai in memoria, dopo che hai eseguito la query, o perchè hai creato un nuovo oggetto e poi aggiornare il database sottostastante chiamando il metodo SubmitChanges sull'oggetto che eredita dalla classe DataContext.

  • Anonymous
    March 26, 2009
    grazie pietro, fino ad ora è la spiegazione più chiara che ho letto sull'argomento. credo che ripasserò di qui più spesso.