LINQ, Entities Framework & ORMs
-
Upload
jug-genova -
Category
Technology
-
view
2.223 -
download
5
description
Transcript of LINQ, Entities Framework & ORMs
![Page 2: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/2.jpg)
LicenzaQuesti lucidi sono rilasciati sotto la licenza Creative Commons
Attribuzione-Non commerciale-Non opere derivate 3.0 Unported.Per leggere una copia della licenza visita il sito web http://creativecommons.org/licenses/by-nc-nd/3.0/ o spedisci una lettera a Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
In due parole, possono essere liberamente usati, copiati e distribuiti purché:
1. Venga citata la fonte originale2. Non vengano usati in ambito commerciale3. Non vengano modificati in nessun modo
![Page 3: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/3.jpg)
Cosa vedremo?
• LINQ
– Cos’è? Requisiti, pubblicità
– Accenni di cosa succede “dietro le quinte”
• LINQ to Objects
• LINQ to SQL
• Panoramica di ADO Entity Framework
• Conclusioni
![Page 4: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/4.jpg)
Cos’è LINQ?
Uno strumento per interrogare in modo uniforme– Oggetti in memoria (LINQ to Objects)
– Database relazionali (LINQ to SQL)
– Documenti XML (LINQ to XML)
– Modelli E/R (LINQ to Entities)
– ...altro... LINQ to Flickr, LINQ to whatever
LINQ non è ORM, ma è un’ottima interfaccia per interrogarli
![Page 5: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/5.jpg)
Cos’ha di tanto speciale LINQ?
• Uniformità ed Estensibilità
• Query a livello di linguaggio
– Type checking
– Nell’IDE:
• Intellisense
• Refactoring
– Non serve escaping niente più (SQL) injection
![Page 6: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/6.jpg)
Cosa serve?
• .NET 3.5/Visual Studio 2008– C# 3 C# 2 + “quello che serve per LINQ”
– il risultato è compatibile con .NET 2.0
• Quindi, tutta “compiler magic”– type inference, quanto basta, e
– zucchero sintattico come se piovesse
• Quindi, è realistico che arrivi in Java– Java 6 = Java 5 C# 2
– Per Java 7 si parla di closure...
![Page 7: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/7.jpg)
LINQ to Objectsstring[] strings = { "g", null, "gENoVa", "jug" };
var query = from s in stringswhere s.Length>2orderby s descendingselect s.ToUpper();
var query2 = from s in querywhere s.StartsWith("G")select s.Length;
strings[1] = "a";
int sum = query2.Sum();
Console.WriteLine("Sum={0}\n", sum);foreach (string s in query) Console.WriteLine(s);
Sum=6
JUGGENOVA
![Page 8: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/8.jpg)
Var• Solo per dichiarare variabili locali, il tipo (inferito) è
quello dell’inizializzatore
• Esempio:int i = 0;var i = 0; // equivalenti, finché non cambia inizializz.
• E’ chiaramente molto comoda con i generici...List<List<string>> lls =
new List<List<string>>();var lls = new List<List<string>>();
• Non solo per i pigri, essenziale in alcuni casi
![Page 9: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/9.jpg)
LINQ to SQLusing (var context = new JUGDataContext()) {
var q = from user in context.Users
where user.lastname.Length>1
select user;
q = from user in q
orderby user.lastname
select user;
foreach (var x in q) // esegue una DB query
Console.WriteLine(x.lastname + " " +x.firstname);
}
![Page 10: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/10.jpg)
ToList/ToArrayvar q = from user in context.Users
orderby user.lastname
select user;
// esegue 10 volte la query
for (int a = 0; a < 10; ++a)
foreach (var x in q) // ...
List<User> l = q.ToList();
// esegue una sola volta sul DB
for (int a = 0; a < 10; ++a)
foreach (var x in l) // ...
![Page 11: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/11.jpg)
Proiezioni e Tipi anonimi
var q = from user in context.Users
orderby user.lastname
select new { user.firstname, user.lastname, fullName = user.firstname+" "+user.lastname } ;
foreach (var x in q)
Console.WriteLine("nome={0}, cognome={1}, nome completo={2}", x.firstname, x.lastname, x.fullName);
Qui var diventa obbligatorio! Che tipo ha x?
Un tipo anonimo, sappiamo solo che ha un campo firstname di tipo string, ecc.
![Page 12: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/12.jpg)
Scorciatoie varie...
var array = new[] { "ciao", "mondo" };
var anA = new A(3) { G=3 };
var anotherA = new A { F=5, G=3 };
var something = new { Answer = 42 };
Nei primi tre casi, al posto di var avrei potuto usare: string [], A e A
![Page 13: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/13.jpg)
Esempio con groupbystring[] strings = { "Gio", "Java", "Genova", "JUG", "Zorro" };
var query = from s in stringsgroup s by s[0] into sameFirstLGrouporderby sameFirstLGroup.Count() ascendingselect new { FirstLetter = sameFirstLGroup.Key,
Words = sameFirstLGroup };
foreach (var g in query) {Console.WriteLine("FirstLetter = {0}",
g.FirstLetter);Console.WriteLine("Words = ");foreach (var w in g.Words)
Console.WriteLine("\t{0}", w);}
FirstLetter = ZWords =
ZorroFirstLetter = GWords =
GioGenova
FirstLetter = JWords =
JavaJUG
![Page 14: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/14.jpg)
Altro zucchero sintattico...
var ls = new List<string>(){ "qui", "quo", "qua" };
var d = new Dictionary<int, string>() { { 1, "pippo" }, { 2, "pluto" } };
Auto-implemented properties:int pippo { get; set; }
![Page 15: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/15.jpg)
Cos’è davvero una query?
• Qualcosa che “trasforma” una sequenza in un’altra
– string[] strings = { "qui", "quo", "qua" };var q = from s in strings select s.Length;
• Ok…cos’è una sequenza?– tutte le “robe foreach-abili”: IEnumerable<T>
![Page 16: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/16.jpg)
Sequenze di “cosi”• IEnumerable<T>
– IEnumerator<T> GetEnumerator()
• IEnumerator<T>
– bool MoveNext()
– T Current { get; }– (... Reset e Dispose che non ci
interessano)
• java.lang.Iterable<T>
– Iterator<T>iterator()
• java.lang.Iterator<T>
– hasNext()
– next()– (... e remove che non ci
interessa)
...
![Page 17: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/17.jpg)
Esempi
Se il risultato è una sequenza di oggetti di tipo R, il tipo della query sarà IEnumerable<R>
• string[] strings = {"qui", "quo", "qua"};IEnumerable<int> q1 = from s in strings
select s.Length;
• IEnumerable<string> q2 = from s in strings select s;
• IEnumerable<string> q3 = strings;
• IEnumerable<bool> q4 = from i in(from s in strings select s.Length) select i > 0;
![Page 18: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/18.jpg)
var q = from user in
/* un certo IEnumerable<User> */
where user.firstname == "Giovanni"
select user;
foreach (var x in q)
Console.WriteLine(x.firstname);
Come può generare il codice corretto?!? La condizione deve diventare del codice .NET, una clausola WHERE in SQL o che altro?
Dipende dal provider... che non conosciamo!
Troppa magia... come funziona?!?
![Page 19: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/19.jpg)
C’è il trucco ;-)
1. Esiste una traduzione che trasforma le query LINQ in una serie di chiamate di metodo
– Traduzione puramente sintattica: il risultato viene poi compilato con le regole usuali
2. La sorgente può essere più specifica di quanto detto prima, per esempio:interface IQueryable<T> : IEnumerable<T>, ...
rappresenta, terminologia mia, le sequenze “LINQ-aware”
![Page 20: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/20.jpg)
Versione tradotta,senza “zucchero sintattico”
var q = /* ... un IEnumerable/IQueryable ... */
.Where(user => user.firstname == "Giovanni")
.Select(user => user);
Ora sì che va meglio! Al posto di un problema ne abbiamo due
1. Cosa sono Where e Select? Sembrano metodi ma non fanno parte di IEnumerable...
2. Cosa gli passiamo?
![Page 21: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/21.jpg)
Extension methods
• E’ possibile aggiungere metodi (implementati) a una qualunque classe/interfaccia
• Visti dall’intellisense (quasi) come gli altri
• Meccanismo molto potente, ricorda l’Aspect Oriented Programming
– sembra fin troppo facile abusarne
![Page 22: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/22.jpg)
Extension methods: come?
• Si usa this come modificatore del primo parametro di un metodo statico public static int m(this T x, int k, ...)
• Il compilatore trasforma le chiamate expr.m(1, 2, 3) dove expr ha tipo T (e non c’è nessun metodo migliore) in:MiaClasseStatica.MioExtMethod(expr, 1, 2, 3)
![Page 23: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/23.jpg)
Esempio di estensione (totalmente inutile)
public static class MyStringExtension {public static int TwiceLength(this string s) {
return s.Length * 2;}
}...Console.WriteLine("ciao".TwiceLength());
// stampa 8, trasformata dal compilatore in:Console.WriteLine(MyStringExtension.
TwiceLength("ciao"));
![Page 24: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/24.jpg)
Lambda Expressions (Closures)
• Fanno finta di essere λ-astrazioni del λ-calcolo , ovvero definizioni di funzioni “inline”Esempi: – (int x, int y) => x + y
rappresenta la funzione che somma x e y– a => a * a
rappresenta la funzione quadrato– (x, y) => { if (x < y) return x; else return y; }
rappresenta la funzione che restituisce il minimo
• Il tipo dei parametri può essere inferito– Se il parametro è uno solo, non servono le parentesi
![Page 25: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/25.jpg)
Lambda Expression (cont.)
Una lambda-expression è, di per sé, totalmente inutile (!) ma può essere convertita in:
• un delegate, in sostanza, in codice .NET che valuta la funzione, oppure in
• un Expression tree, (codice .NET che costruisce) una struttura dati che rappresenta l’espressione, che il provider trasformerà in una qualche forma più furba per l’esecuzione (per esempio, una query SQL per un DB relazionale)
![Page 27: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/27.jpg)
Riprendiamo la versione “dietetica”
var q = /* ... */
.Where(user => user.firstname == "Giovanni")
.Select(user => user);
In base al tipo della sorgente:
public static IEnumerable<T> Where<T>(this IEnumerable<T> source,Func<T, bool> predicate)
public static IQueryable<T> Where<T>(
this IQueryable<T> source,
Expression<Func<T, bool>> predicate)
![Page 28: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/28.jpg)
Ma allora, cosa devo usare?
Dipende, comunque un IEnumerable si converte facilmente con asQueryable
Non è (sempre) un cast:
int[] ints = { 1, 2, 3 };
IQueryable<int> iq = ints.AsQueryable();
IQueryable<T>
IEnumerable<T>
![Page 29: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/29.jpg)
Limiti dell’approccio
• Alcune espressioni possibili solo con LINQ to Objects, per esempio in LINQ to SQL:var q = from user in context.Users
where user.MyMethod()>0 /* boom */
select user.MyMethod() /* ok */ ;
– Comunque, molti (tutti?) metodi standard di numeri/stringhe/date vengono tradotti
• Mi sembra sconsigliabile, ma limitandosi a LINQ to Objects è possibile modificare gli oggetti visitati
![Page 31: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/31.jpg)
ADO Entities Framework
• E’ un ORM, al di là di quello che sostiene M$
• Permette di lavorare a livello di Modello E/R(ereditarietà, relazioni molti-a-molti, ...)
• Si può interrogare via:
– Entities SQL (SQL), per esempio:SELECT VALUE c FROM E.Contacts AS cWHERE c.FirstName='Pippo'
– LINQ to EntitiesLa sintassi è quella che vi aspettate
![Page 32: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/32.jpg)
Mapping
• Descritto da tre file XML
– Ma VS li nasconde abbastanza
Modello Concettuale
(E/R).CSDL
Conceptual Schema Definition Language
Mapping.MSLMapping
Specification Language
Store Schema
.SSDLStore Schema
Definition Language
(tipicamente)
DB RelazionaleOggetti
![Page 34: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/34.jpg)
EntityContext
Dai file XML otteniamo:
• Le classi (parziali) corrispondenti ai tipi entità
• Una classe QualcosaEntityContext (che estende ObjectContext) che ci permette di dialogare con il modello, tramite:– proprietà che corrispondono agli insiemi entità
– metodi AddTo
Il contesto materializza gli oggetti e traccia i cambiamenti, salvati con SaveChanges
![Page 35: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/35.jpg)
Esempio di inserimento datiusing (var context = new JUGEntities()) {
User u = new User() { username = "Gio",firstname="g", lastname="l" };
Role r = new Role() { rolename = "Admin" };u.Roles.Add(r);Document d = new ToDo() { Author = u,
title = "demo", what="boh" };context.AddToDocuments(d);context.SaveChanges();// tutti gli oggetti vengono salvati e// l'ordine delle insert e` automatico
}
![Page 36: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/36.jpg)
Esempio di interrogazione
using (var context = new JUGEntities()) {
var q = from d in context.Documents.Include("Author.Roles")
where d.Author.username=="Gio"
select d;
var aDoc = q.First();
//aDoc.AuthorReference.Load();
User author = aDoc.Author;
Console.WriteLine("Author: {0}\nRoles:", author.firstname);
//author.Roles.Load();
foreach (Role r in author.Roles)
Console.WriteLine("\t{0}", r.rolename);
}
![Page 37: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/37.jpg)
Esempio di modifica/cancellazione
using (var context = new JUGEntities()) {
var todos = (from d in context.Documents.OfType<ToDo>()
select d).ToArray();
context.DeleteObject(todos[0]);
todos[1].what = "blabla";
context.SaveChanges();
}
![Page 38: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/38.jpg)
LINQ to SQL vs LINQ to Entities
Visto che, alla fin fine, si parla di DB relazionali, un confronto è inevitabile.
Alcune domande abbastanza ovvie sono:
• LINQ to SQL è un ORM?
• Quanto si assomigliano?
• Posso passare dall’uno all’altro con facilità?
![Page 39: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/39.jpg)
LINQ to... SQL Entities
E’ un ORM No Sì
Cosa si “vede”? Delle tabelle, relazioni 1-n Entità e Relazioni (anche n-m)
Ereditarietà No (sì ma...) Sì
Transazioni No (ma basta wrappare in ScopeTransaction)
Si (su DB singolo, se non basta: ScopeTransaction)
Query SQL generate Ragionevoli A volte ragionevoli
Da modello a DB e viceversa?
No (ma avrebbe senso?) Solo da VS 2010, purtroppo
Sincronizzazione schema DB?
No (mi sembra, VS2010?), non grave: classi parziali
Sì
Editor Visuale Sì Sì al 90% (speriamo in VS 2010...)
Lazy/eager loading Per context/implicito Per query/esplicito
Locking ottimistico Di default su tutto Sì, ma di default su nulla
Single/SingleOrDefault Sì No! (Eccezione a runtime)
![Page 40: LINQ, Entities Framework & ORMs](https://reader035.fdocuments.net/reader035/viewer/2022081721/554ebd01b4c905064d8b4668/html5/thumbnails/40.jpg)
Conclusioni• Oggi: LINQ to
– Objects: molto comodo
– XML: esiste, non l’ho mai usato
– SQL: ok, ma alle “ORMeggia” a sproposito
– Entities: interessante, probabilmente immaturo
• Domani?– LINQ in Java?
– LINQ to (N)Hibernate: abbastanza non-m$ per essere apprezzato da tutti?
– PLINQ, un .AsParallel() rende la query parallela!