Utilizzare Entity SQL per eseguire query in Entity Framework

di Stefano Mostarda, in LINQ,

Quando si deve eseguire una query tramite Entity Framework, LINQ to Entities è senza dubbio la via più semplice ed immediata. La sua natura tipizzata unita all'autocompletion di Visual Studio ed al compile-time checking del compilatore permette di creare query in maniera molto semplice e immediata. Qualunque altra tecnica creata precedentemente per creare un Query Object è stata spazzata via dall'introduzione di LINQ. Ne è la riprova il fatto che altri framework, NHibernate su tutti, abbiano introdotto il proprio provider per LINQ al fine di semplificare la scrittura delle query.

Tuttavia LINQ è una tecnologia "giovane". Il suo annuncio risale alla PDC del 2005 e la sua inclusione nel .NET Framework è avvenuta con la versione 3.5. Entity Framework ha radici più vecchie e la sua storia risale a ben prima dell'uscita di LINQ. Non avendo a disposizione questo tool, il team doveva mettere a disposizione degli sviluppatori qualcosa che permettesse di effettuare le query. La scelta è stata creare un linguaggio SQL-like che è stato battezzato con il nome di Entity SQL.

Questo linguaggio è stato creato appositamente per Entity Framework e quindi è stato studiato per poterne sfruttare appieno le funzionalità. Inoltre, essendo in giro sin dalla prima beta di Entity Framework, la sua potenza e completezza sono superiori a LINQ to Entities. Non è infatti un caso che ci siano operazioni che possono essere effettuate solo tramite Entity SQL o che producano un codice SQL più ottimizzato rispetto a LINQ to Entities.

In questo articolo parleremo di Entity SQL, di come scrivere le query, recuperare i risultati e sfruttare nel migliore dei modi le sue caratteristiche.

La prima cosa da tenere a mente è che Entity SQL è string-based (ovvero basato su stringhe testuali). A differenza delle query scritte con LINQ to Entities, non c'è tipizzazione, non c'è compile-time checking e Visual Studio non offre alcun aiuto. Qualunque forma di errore può essere scoperta solo a run time. Sicuramente questa caratteristica rende Entity SQL meno "affascinante", ma allo stesso tempo apre scenari interessanti come, ad esempio, la possibilità di creare query dinamicamente. Per fare questo in LINQ to Entities bisognerebbe scrivere molto codice in più.

Preparazione

Prima di partire con gli esempi, vediamo il modello che useremo nel corso dell'articolo. Il modello è molto semplice in quanto abbiamo semplicemente una classe Order ed una classe OrderDetail. L'ordine ha una proprietà ShippingAddress con indirizzo, città, CAP e stato. Sebbene l'esempio sia molto semplice, è più che sufficiente per mostrare le caratteristiche che verranno spiegate nell'articolo.

Infine per testare e visualizzare il risultato di una query, esise un tool molto interessante sviluppato da Zlatko Michailov che è un membro del team di Entity SQL. Il tool può essere scaricato direttamente da codeplex.

Anatomia di una query

Una query Entity SQL è composta da 4 blocchi:

SELECT VALUE c FROM OrderITEntities.Orders as c

La parola chiave SELECT è obbligatora e ogni query deve cominciare con essa. Dopo SELECT si devono specificare le proprietà da recuperare. In questo caso vuole ottenere l'intera entità, quindi si usa la parola chiave VALUE. Successivamente si specifica l'Entity Set nella clausola FROM ad infine l'alias. Notare che a differenza del linguaggio SQL, a cui Entity SQL si ispira, l'alias è obbligatorio.

Processare il risultato di una query

Una volta scritta la query, la si deve eseguire all'interno del codice. Per fare questo si utilizza il metodo CreateQuery<T> della classe ObjectContext, dove T è il tipo dell'oggetto restituito dalla query, passando in input la query.

var order = ctx.CreateQuery<Order>
  ("SELECT VALUE c FROM OrderITEntities.Orders as c WHERE c.CustomerID = 1");

La variabile order contiene una lista degli ordini e può essere processata come qualunque altra lista.

Filtrare i dati

Generalmente la prima operazione che si cerca di fare su un set di dati è il filtro. Ad esempio, si possono cercare solo alcuni ordini come quelli più recenti, quelli di un determinato cliente o altri ancora. Per chi è abituato al linguaggio SQL questa è un'operazione molto semplice.

Supponendo di voler recuperare tutti gli ordini del cliente con ID pari a 1, la query è:

SELECT VALUE c 
FROM OrderITEntities.Orders as c
WHERE c.CustomerID = 1

La clausola WHERE in questa query è identica a quella che si scriverebbe in SQL. Tuttavia le cose cambiano se si esegue un filtro per recuperare gli ordini che vengono spediti verso una determinata città, in quanto viene coinvolta una proprietà complessa.

SELECT VALUE o FROM OrderITEntities.Orders AS o 
WHERE o.ShippingAddress.City = "ROMA"

Poichè City è contenuta nel tipo complesso, si arriva ad essa come se si navigasse la proprietà all'interno del codice C# o VB e questo rispetto ad SQL è un notevole cabiamento. Ovviamente, essendo la query una stringa, non si riceve alcun aiuto da Visual Studio. Tuttavia questo tipo di sintassi permette di scrivere la query in maniera molto semplice e diretta.

3 pagine in totale: 1 2 3
Contenuti dell'articolo

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti