2010-10-14 45 views
5

給出LINQ to SQL .dbml文件中的兩個類,其中具有以下特性。通過擴展方法將linq中的邏輯封裝爲sql查詢

Customer 
    CustomerId 
    FirstName 
    LastName 
    AddressId 

Address 
    AddressId 
    Street 
    City 
    State 
    Zip 

您可以構造一個LINQ查詢,如下所示。

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

} 

現在讓我們假設你想排除將郵寄地址放在一起的邏輯。你可以完成的兩種方法是向Customer類添加一個新的屬性,或者創建一個擴展方法。

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

你現在可以使用其中的一個,你會得到正確的結果

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

} 

用這兩種方法的問題是,這樣做將導致那裏是一個額外的往返到數據庫爲您檢索的每一行。初始查詢將從客戶表中取回信息,然後在評估郵寄地址時需要單獨對每個地址記錄進行分級。

是否有辦法將這種邏輯封裝起來,並以這種方式將它與客戶類綁定在一起,以至於不需要任何額外的往返數據庫?

我認爲必須有一些方法來創建一個擴展方法,而不是返回一個表達式而不是一個字符串。我對嗎?如果是這樣,我將如何做到這一點?

回答

3

我知道這是不是正是你所尋找的東西,但你可以這樣做:

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

然後,它只會讓自己的行程作爲地址與用戶檢索。

+0

感謝理查德,這確實有效,但你是對的,這不是我想找到的原因有兩個。首先,調用方法需要知道構造'MailingAddress'涉及的內容,即它需要地址表。其次,讓我們說地址表實際上包含了超過5個字段,我相信這樣做會帶來比我們實際需要的更多的數據。 – eoldre 2010-10-14 19:18:12