2011-11-04 31 views
1

這是我的表的簡化SQL,它被轉換爲LINQ to SQL模型。LINQ to SQL分離和數據結構的可重用性

CREATE TABLE Campaign (
    Id int PRIMARY KEY, 
    Name varchar NOT NULL 
); 
CREATE TABLE Contract (
    Id int PRIMARY KEY, 
    CampaignId int NULL REFERENCES Campaign(Id) 
); 

現在我有這樣的類(這些都是在不同的命名空間,從數據模型沒有實體類)。

public class CampaignInfo { 
    public static CampaignModel Get(DataModel.CampaignInfo campaign) { 
     return new CampaignInfo { 
       Id = campaign.Id, 
       Name = campaign.Name, 
       Status = CampaignStatus.Get(c) 
     }; 
    } 
    public int Id {get; set;} 
    public int Name {get; set;} 
    public CampaignStatus { get; set;} 
} 

public class CampaignStatus { 
    public static CampaignStatus Get(DataModel.Campaign campaign) { 
     return new CampaignStatus { 
       Campaign = campaign.Id, // this is just for lookup on client side 
       ContractCount = campaign.Contracts.Count() 
       // There is much more fields concerning status of campaign 
     }; 
    } 
    public int Campaign { get; set; } 
    public int ContractCount {get; set;} 
} 

而且比我跑的查詢:

dataContext.Campaigns.Select(c => CampaignInfo.Get(c)); 

其他代碼塊可以做這樣的事情:

dataContext.Campaigns.Where(c => c.Name == "DoIt").Select(c => CampaignInfo.Get(c)); 

或者我想狀態的列表活動:

dataContext.Campaigns.Select(c => CampaignStatus.Get(c)); 

注意:這些調用的結果將轉換爲JSON,因此不需要跟蹤原始數據庫實體。

正如你所看到的,有兩個目標。控制從數據庫中獲取數據並在其他地方重用這些結構。然而,這種方法是一個巨大的錯誤,因爲那些類返回對象並在表達式樹中使用它。

現在我明白了,它不能神奇地創建表達式來使整個事情與一個查詢。相反,它會分別計算每個廣告系列的數量。在相當複雜的情況下,這是醜陋的放緩。

是否有一些簡單的方法來實現這個目標?我想,這些類應該返回一些表達式,但我對這個領域完全陌生,我不知道該怎麼做。在查詢

using(var dataContext = new DataModel.ModelDataContext()) 
{ 
    dataContext.Campaigns.Select(c => new { 
      Id = c.Id, 
      Name = c.Name, 
      Status = new CampaignStatus() 
      { 
       ContractCount = c.Contracts.Count() 
      } 
     }) 
} 

+0

我想,我已經想出了一部分。現在使用pastebin,所以在這裏不會太長。 http://pastebin.com/rttTgxyJ。而不是對象,我返回'Expression >'。但是我無法弄清楚如何用CampaignInfo打包CampaignStatus。 – FredyC

回答

3

如果我理解正確,一般問題是您有一些業務邏輯,您不希望在整個代碼中重複(幹)。你希望能夠在你的LINQ方法中使用這個邏輯。

LINQ(通過表達式樹)的通用解決方案是創建一個篩選器或轉換函數,該函數返回IQueryable,因此您可以在將該查詢發送到數據庫之前對該查詢進行進一步處理。

這裏是一個辦法做到這一點:在地方

// Reusable method that returns a query of CampaignStatus objects 
public static IQueryable<CampaignStatus> 
    GetCampaignStatusses(this IQueryable<Compaign> campaigns) 
{ 
    return 
     from campaign in campaigns 
     new CampaignStatus 
     { 
      Campaign = campaign.Id, 
      ContractCount = compaign.Contracts.Count() 
     }; 
} 

有了這個,你可以寫下面的代碼:

using (var db = new DataModel.ModelDataContext()) 
{ 
    return 
     from campaign in db.Campaigns.WithContractCount() 
     from status in db.Campaigns.GetCampaignStatusses() 
     where campaign.Id == status.Campaign 
     select new 
     { 
      Id = campaign.Id, 
      Name = campaign.Name, 
      Status = status 
     }; 
} 

有一個返回IQueryable允許你做的所有的方法有些額外的操作,沒有這種方法知道它。舉例來說,你可以添加過濾:

 from campaign in db.Campaigns.WithContractCount() 
     from status in db.Campaigns.GetCampaignStatusses() 
     where campaign.Id == status.Campaign 
     where campaign .Name == "DoIt" 
     where status .ContractsCount < 10 
     select new 
     { 
      Id = campaign.Id, 
      Name = campaign.Name, 
      Status = status 
     }; 

或添加額外的屬性輸出:

 from campaign in db.Campaigns.WithContractCount() 
     from status in db.Campaigns.GetCampaignStatusses() 
     where campaign.Id == status.Campaign 
     select new 
     { 
      OtherProp = campaign.OtherProp, 
      Id = status.Campaign, 

      Name = campaign.Name, 
      Status = status 
     }; 

這將轉換到一個有效的SQL查詢。查詢不會從嚴格需要的數據庫中獲取更多記錄或列。

+0

謝謝,但要麼我不明白,或者它不是我正在尋找的。 'CampaignStatus'中肯定會有更多的字段,我想重複使用'Campaign'類。我已經更新了更多的例子。 – FredyC

+0

@FredyC:我更新了我的答案。我仍然認爲這是你需要的。 – Steven

+0

我仍然缺少那裏的一部分。您只將一個變量放到狀態屬性中,但我需要更多的變量。或者更具體一些。我需要整個Status對象併成爲Campaign的一部分,或者可以獨立運行。 – FredyC

0

您可以使用類似。

+0

這正是不想要的,因爲可重用性:)在其他代碼中,我想獲取廣告系列的狀態。 'ContractStatus'中有更多的屬性,這只是簡短的版本。 – FredyC