Riutilizzare porzioni di espressioni LINQ

di Cristian Civera, in .NET 3.5,

Se anche voi usate in alcuni progetti LINQ to SQL come DAL, vi troverete un domain model e le classi create tramite il DBML. Questo perché le prime vengono usate nello strato di presentazione e in quello business, mentre le seconde utilizzate all'interno del DAL realizzato con LINQ to SQL.
Di conseguenza ci ritroviamo a dover mappare le due entità in modi più o meno complessi. Poniamo di avere la classe Customer di LINQ to SQL e quella del domain model (per semplificare con mapping 1:1):

public class CustomerL2S
{
   public int ID { get; set; }
   public string Description { get; set; }
}
public class Customer
{
   public int ID { get; set; }
   public string Description { get; set; }
}

In un ipotetico metodo GetSingle che dato l'ID ti dà l'entità, scriviamo qualcosa del genere:

var customer = from c in customers
            where c.ID == 1
            select new Customer
            {
                ID = c.ID,
                Description = c.Description
            };

Poi magari un metodo di List restituisce tutti i Customer, senza filtrarli e purtroppo ci tocca duplicare l'intera query, compreso tutto il mapping, senza la clausola where. Potremmo essere tentati di fare una funzione, così:

var customer = from c in customers
            where c.ID == 1
            select GetCustomer(c);

Purtroppo questa tecnica non funziona, perché passiamo una funzione managed al motore di LINQ to SQL che non può passarla a SQL Server. Il problema non sta nella funzione, ma in ciò che essa fa. Infatti la soluzione sta nel lavorare sempre a livello di expression tree. Potremmo infatti creare un extension method (solo per comodità nella chiamata) specifico per il Customer che effettua il mapping che ci permetta di riutilizzarlo più volte:

public static class Extentions
{
   public static IQueryable<Customer> SelectToCustomer(this IQueryable<CustomerL2S> source)
   {
       return source.Select(c => new Customer
       {
           ID = c.ID,
           Description = c.Description
       });
   }
}

Nella funzione accettiamo un IQueryable specifico per l'entità CustomerL2S e sfruttando l'extension method select effettuamo il mapping, ma sempre a livello di espressione, consentendola di portarla su SQL Server. L'utilizzo poi è semplice:

var customer = (from c in customers
               where c.ID == 1
               select c).SelectToCustomer();

Il doppio select è d'obbligo per via della query syntax, ma non è un problema poiché la query SQL generata è corretta.

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.

Nella stessa categoria
I più letti del mese