ADO.NET Entity Framework è un ORM targato Microsoft che tra le principali caratteristiche ha il grande punto di forza di poter essere utilizzato con LINQ to Entities per facilitare l'interrogazione e la manipolazione dei dati. Questo è possibile grazie a LINQ e in particolare all'interfaccia IQueryable che permette di creare un grafo di oggetti di tipo Expression che sono in grado di rappresentare un espressione al fine di consentire a motori, come LINQ to SQL o LINQ to Entities, di trasformarlo in una query ANSI SQL.
Il difetto di questo approccio è che tale espressione, e in generale LINQ, sono legati alla tecnologia .NET e non possono essere trasportati al di fuori di questo mondo. Per esempio, se si sviluppa un servizio WCF che permette l'interrogazione dei prodotti, è necessario che si definisca un'operazione per ottenere una lista ed eventualmente fornire come parametro una struttura che permetta di filtrare per uno o più campi, di ordinare o di paginare. Qualunque scelta si faccia, è molto probabile che la struttura definita sia comunque limitata e non adatta a coprire tutte le esigenze che i potenziali consumer del servizio possano aver bisogno.
Sul sito di MSDN è a disposizione all'indirizzo http://code.msdn.microsoft.com/exprserialization del codice di esempio che mostra come serializzare e deserializzare in XML un Expression, perciò l'idea di questo script è di proporre di usare tale codice per creare un servizio che riceva l'espressione della query da creare e la esegua con LINQ to Entities (nell'esempio MSDN viene usato LINQ to Sql).
Si prenda in esame questo codice che effettua una normale query:
NorthwindEntities ne = new NorthwindEntities(); // Preparazione della query da effettuare string s = "Italy"; IQueryable query = ne.ProductSet.Where(p => p.UnitPrice > 0 && p.Suppliers.Country == s);
La proprietà query.Expression rappresenta il grafo di oggetti dell'espressione che non è ancora stata eseguita. Il ToString restituisce il seguente simil codice C#:
value(System.Data.Objects.ObjectQuery`1[EFWebApplication.Product]).Where(p => ((p.UnitPrice > Convert(0)) && (p.Suppliers.Country = value(EFWebApplication._Default+<>c__DisplayClass0).s)))
La parola value sta ad indicare una costante che in questo caso è ObjectQuery
Ecco quindi come risulta facile, con le classi incluse nello script, serializzare una query:
// Creazione serializzatore delle espressioni ExpressionSerializer serializer = new ExpressionSerializer(); // Convertitore speciale apposito per Entity Framework serializer.Converters.Add(new EFCustomExpressionXmlConverter(ne, serializer)); // Serializzo l'expression in xml xmlExpression = serializer.Serialize(query.Expression);
Di seguito invece come deserializzare l'espressione e creare una query per l'entità Product:
// Deserializzo l'expression dall'xml Expression ex = serializer.Deserialize(xmlExpression); // Creo la query sulla base dell'expression deserializzata IQueryable<Product> r = ((IQueryable)ne.CreateQuery<Product>("*")).Provider.CreateQuery<Product>(ex);
Il limite principale di questa tecnica risiede che non si possono effettuare query complesse laddove vengono valutate classi presenti sul consumer. Queste infatti non possono essere serializzate e si può fare solo riferimento a variabili calcolate prima della preparazione dell'expression. Non è possibile inoltre usare delegate ad eccezione delle lampda e non è possibile fare query miste con LINQ to *.
Con questa tecnica un servizio può ricevere come parametro l'XML dell'espressione oppure, per automatizzare il tutto, si può valutare l'uso di un DataContractSerializerOperationBehavior per specificare il surrogate per la serializzazione tramite DataContractSerializer dell'Expression o lavorare direttamente con un IClientMessageInspector/IDispatchMessageInspector per intervenire sull'XML SOAP.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Le novità di Entity Framework 8
Utilizzare QuickGrid di Blazor con Entity Framework
Change tracking e composition in Entity Framework
Persistere la ChatHistory di Semantic Kernel in ASP.NET Core Web API per GPT
Filtrare i dati di una QuickGrid in Blazor con una drop down list
Filtering sulle colonne in una QuickGrid di Blazor
Supporto ai tipi DateOnly e TimeOnly in Entity Framework Core
Utilizzare EF.Constant per evitare la parametrizzazione di query SQL
Usare le navigation property in QuickGrid di Blazor
Generare velocemente pagine CRUD in Blazor con QuickGrid
Utilizzare il metodo CountBy di LINQ per semplificare raggruppamenti e i conteggi