2010-10-14 5 views
5

Gegeben zwei Klassen in Ihrer LINQ to SQL .dbml-Datei mit den folgenden Eigenschaften.Verkapselung Logik in einer Linq zu SQL-Abfrage über Erweiterungsmethode

Customer 
    CustomerId 
    FirstName 
    LastName 
    AddressId 

Address 
    AddressId 
    Street 
    City 
    State 
    Zip 

Sie könnten eine LINQ-Abfrage wie die folgende erstellen.

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(); 

} 

Jetzt wollen wir sagen, dass Sie die Logik zum Zusammenstellen der Postanschrift verkapseln wollten. Zwei Möglichkeiten, die Sie erreichen könnten, wären das Hinzufügen einer neuen Eigenschaft zur Customer-Klasse oder das Erstellen einer Erweiterungsmethode.

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; 
     } 
    } 
} 

Sie jetzt einen von denen nutzen könnte, und Sie würden die richtigen Ergebnisse

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(); 

} 

Das Problem mit diesen beiden Möglichkeiten erhalten wird, dass dadurch verursacht dort eine zusätzliche Hin- und Rückfahrt zu der sein Datenbank für jede Zeile, die Sie abrufen. Die anfängliche Abfrage zieht die Informationen aus der Customer-Tabelle zurück und muss dann jeden Adressdatensatz einzeln abstufen, wenn er nach der Postanschrift auswertet.

Gibt es eine Möglichkeit, diese Logik zu kapseln und sie so an die Kundenklasse zu binden, dass Sie keine zusätzlichen Rundreisen zur Datenbank benötigen?

Ich denke, dass es eine Möglichkeit geben muss, eine Erweiterungsmethode zu erstellen, die stattdessen einen Ausdruck anstelle einer Zeichenfolge zurückgibt. Habe ich recht? Wenn ja, wie würde ich das tun?

Antwort

3

Ich weiß, das ist nicht genau das, was Sie suchen, aber Sie können dies tun:

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

Dann wird es nur eine Reise machen, wie die Adresse mit dem Kunden abgerufen werden.

+0

Danke Richard, das funktioniert, aber du hast Recht es ist nicht ganz das, was ich hoffe, aus zwei Gründen zu finden. Zuerst muss die aufrufende Methode etwas darüber wissen, was mit der Erstellung von "MailingAddress" zusammenhängt, dh dass sie die Adresstabelle benötigt. Zweitens, sagen wir mal, dass die Adresstabelle tatsächlich mehr als 5 Felder enthält, glaube ich, dass dies viel mehr Daten zurückbringen würde, als wir tatsächlich benötigen. – eoldre

Verwandte Themen