Riutilizzare porzioni di espressioni LINQ

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.

Nella stessa categoria

Commenti

Aggiungi un nuovo commento »»»
Per inserire un commento, devi registrarti alla nostra community.

© 1998-2008 - Ricciolo.NET - Il blog di Cristian "Ricciolo" Civera

TagCloud
BLOG INFO
  • Post: 177
  • Commenti: 76
  • TrackBacks: 39
  • Feed blog e contenuti tecnici: RSS
  • Feed blog: RSS Atom OPML

MVP
CATEGORIE
I PIÙ LETTI DEL MESE
IN EVIDENZA