2010-10-14 15 views
5

Dato due classi nel file LINQ to SQL .dbml con le seguenti proprietà.logica di incapsulamento in una query da linq a sql tramite il metodo di estensione

Customer 
    CustomerId 
    FirstName 
    LastName 
    AddressId 

Address 
    AddressId 
    Street 
    City 
    State 
    Zip 

È possibile creare una query LINQ come la seguente.

using(var db = new MyDataContext()) 
{ 
    results = db.Customers 
     .Where(c => c.LastName.BeginsWith("o")) 
     .Select(c => new 
      { 
       c.CustomerId, 
       MailingAddress = c.FirstName + " " 
        + c.LastName 
        + Environment.NewLine 
        + c.Address.Street 
        + Environment.NewLine 
        + c.Address.City + ", " 
        + c.Address.State + " " 
        + c.Address.Zip 
      }).ToList(); 

} 

Ora diciamo che si desiderava escludere la logica per mettere insieme l'indirizzo postale. Due modi che potresti ottenere sarebbe aggiungere una nuova proprietà alla classe Customer o creare un metodo di estensione.

public static class CustomerExtensions 
{ 
    public static string GetMailingAddress(this Customer cust) 
    { 
     return cust.FirstName + " " 
        + cust.LastName 
        + Environment.NewLine 
        + cust.Address.Street 
        + Environment.NewLine 
        + cust.Address.City + ", " 
        + cust.Address.State + " " 
        + cust.Address.Zip; 
    } 
} 

public partial class Customer 
{ 
    public string MailingAddress 
    { 
     get 
     { 
      return this.FirstName + " " 
        + this.LastName 
        + Environment.NewLine 
        + this.Address.Street 
        + Environment.NewLine 
        + this.Address.City + ", " 
        + this.Address.State + " " 
        + this.Address.Zip; 
     } 
    } 
} 

si potrebbe ora usare uno di questi e si dovrebbe ottenere i risultati corretti

using(var db = new MyDataContext()) 
{ 
    results = db.Customers 
     .Where(c => c.LastName.BeginsWith("o")) 
     .Select(c => new 
      { 
       c.CustomerId, 
       c.MailingAddress, //new property 
       Address2 = c.GetMailingAddress() // new extension method 
      }).ToList(); 

} 

Il problema con entrambi questi modi è che così facendo farà sì che ci sia un viaggio in più intorno al database per ogni riga che si recupera. La query iniziale estrarrà le informazioni dalla tabella Customer e quindi dovrà valutare ogni record dell'indirizzo singolarmente quando valuta l'indirizzo postale.

C'è un modo per incapsulare questa logica e legarla alla classe cliente in modo tale da non aver bisogno di ulteriori viaggi di andata e ritorno nel database?

Penso che ci sia un modo per creare un metodo di estensione che restituisca invece un'espressione invece di una stringa. Ho ragione? Se sì, come lo farei?

risposta

3

So che questo non è esattamente quello che stai cercando, ma si può fare questo:

var options = new DataLoadOptions(); 
options.LoadWith<Customer>(c => c.Address); 
db.LoadOptions = options; 

allora sarà solo fare un viaggio come l'indirizzo viene recuperato con il Cliente.

+0

Grazie Richard, funziona ma hai ragione, non è proprio quello che spero di trovare per due motivi. In primo luogo, il metodo di chiamata deve quindi sapere qualcosa su ciò che è coinvolto nella costruzione di "MailingAddress", cioè che richiede la tabella degli indirizzi. In secondo luogo, diciamo che la tabella degli indirizzi conteneva in realtà molti più di 5 campi, credo che fare ciò porterebbe indietro molti più dati di quanti ne abbiamo effettivamente bisogno. – eoldre

Problemi correlati