2010-09-05 155 views
5

避免重複投影代碼我試圖解決類似僅從完全相反的方向這裏在實體框架

Initializing strongly typed objects in LINQ to Entities

所描述的存在的問題。我在我的倉庫中有許多函數,所有函數都返回相同形狀的數據。問題是我的投影代碼:

select new pocoClass 
{ 
    // complex projection that is several pages long includes grabbing a graph of data 
} 

目前它存在於存儲庫中的每個查詢。我試圖將它移動到一個對象初始值設定項中,但這給我帶來了可怕的「LINQ to Entities支持只有無參數的構造函數和初始值設定項」。問題。

我曾嘗試分裂成兩個查詢

var candidates = (from thing in _entities.whatever 
    where (complex.stuff==true) 
    select thing); 

var final = (from thing in candidates.AsEnumerable() 
    let x = thing.ITEMS.Where(blah=>blah.blah==param) 
    let y = x.OTHERITEMS.FirstOrDefault() 
    select new pocoClass(thing,x,y); 

但這裏最終總是空,並在新的pocoClass代碼永遠不會被調用。我在上面包含了let x & y,因爲這些投影在每次投影之間總會有所不同。

那麼,我必須返回到我的投影的多個副本,或者有另一種方式嗎?

回答

12

我不確定這是否適用於您,但我經常做的是創建投影方法,其中需要使用IQueryable並返回IQueryable以將域對象轉換爲DTO。他們看起來很像這樣:

public static IQueryable<CustomerDTO> ToCustomerDTO(
    IQueryable<Customer> customers) 
{ 
    return 
     from customer in customers 
     select new CustomerDTO() 
     { 
      ... 
     }; 
} 

這使我可以在一個地方做這個預測。在我業務層的幾個地方,我稱之爲這種方法。

有幾件事情需要注意,雖然:

  • 確保這些投影方法不包含任何業務邏輯。有任何使用情況特定的過濾器會很糟糕。
  • 有時候您有一個DTO,其中包含一個複雜的對象圖,您希望從單個查詢中有效地從數據庫中提取該對象圖。有一點創造力,這往往是可能的,但不是當返回IQueryable。在這種情況下,我返回一組DTO。
  • 我將這些投影方法作爲靜態方法放在DTO類中。雖然這不是一個非常乾淨的設計,但它發現它使代碼非常易於維護。

我希望這有助於。

+0

幾乎 - 它的業務邏輯問題 - 在我的例子中是在投影之前爲每個客戶評估的let語句。 – Andiih 2010-09-05 14:59:41

+0

其實這足以給我一個解決方案。我創建了一個新的簡化的DTO中間類,我可以通過複製六個值來進行項目設計:每個類都是一個完整的EF實體。然後,我使用您的解決方案將這些實體進行最終投影。不知道它會如何表現,但它確實整潔! – Andiih 2010-09-05 15:27:25

+0

@Andiih:您將不得不使用SQL分析器來查看在後臺執行多少查詢。 EF將會在封底之後執行很多查詢,這是一個很好的改變。技術 - 當然 - 有其侷限性。如果您對性能不滿意,並且無法知道如何在單個查詢中獲得此信息,那麼也許我可以爲您提供幫助。在這種情況下,請在此處開始一個新問題,並在此處放置一個鏈接。乾杯 – Steven 2010-09-05 16:40:52