2010-12-10 173 views
1

我想從LinQ語句創建一個實體對象,但我不想加載它的所有列。實體框架 - LinQ投影問題

我的ORDERS對象有很多列,但我只想檢索REFERENCE和OPERATION列,這樣SQL語句和結果會更小。

這LinQ在聲明中正常工作,並加載所有我的對象屬性:

var orders = (from order in context.ORDERS 
      select order); 

而下面的語句未能

var orders = (from order in context.ORDERS 
       select new ORDERS 
       { 
        REFERENCE = order.REFERENCE, 
        OPERATION = order.OPERATION 
       }); 

拋出的錯誤是隻加載了我的兩個對象的屬性:

The entity or complex type 'ModelContextName.ORDERS' cannot be constructed in a LINQ to Entities query.

什麼問題?難道不可能通過這種方式部分加載對象嗎?

非常感謝您的回答。


ANSWER

好吧,我應該感謝你們Yakimych和Dean因爲我用你的答案的兩個,現在我有:

var orders = (from order in context.ORDERS 
       select new 
       { 
        REFERENCE = order.REFERENCE, 
        OPERATION = order.OPERATION, 
       }) 
       .AsEnumerable() 
       .Select(o => 
         (ORDERS)new ORDERS 
         { 
          REFERENCE = o.REFERENCE, 
          OPERATION = o.OPERATION 
         } 
     ).ToList().AsQueryable(); 

而且我得到正是我想要的SQL語句不完美,但它只返回我需要的2列(和另一列包含每行「1」,但我不知道爲什麼暫時) - 我也嘗試用此方法構造子對象,它運作良好。

回答

2

不,您不能投影到映射對象上。您可以使用匿名類型來代替:

var orders = (from order in context.ORDERS 
       select new 
       { 
        REFERENCE = order.REFERENCE, 
        OPERATION = order.OPERATION 
       }); 
+0

好的,我已經試過這個,但是我怎麼能把這個匿名對象轉換成我的實體類型呢? – mbp 2010-12-10 12:07:41

+2

您不能將其映射到實體。您可以爲此創建自定義對象(DTO),但不能部分加載實體,因爲當您嘗試更改和安全它時,EF不知道如何處理它。 – Steven 2010-12-10 13:21:00

0

我認爲這個問題是創建查詢本身內的新的實體,因此,如何嘗試此:

context.ORDERS.ToList().Select(o => new ORDERS 
{ 
    REFERENCE = o.REFERENCE, 
    OPERATION = o.OPERATION 
}); 
+0

這不會解決SQL查詢的問題。它將與您獲取整個對象並從所有字段獲取數據一樣。在執行之後,您將結果轉換到內存中。但是,事後沒有這樣做的意義。 – Yakimych 2010-12-10 17:50:52

+0

請檢查我的第一篇文章,因爲我無法在這裏發佈源代碼。 – mbp 2010-12-14 08:58:32

2

上述解決方案的問題是,從當你調用AsEnumerable()時,查詢將在數據庫上執行。在大多數情況下,它會沒事的。但是,如果您使用某個大型數據庫,則獲取整個表(或視圖)可能不是您想要的。所以,如果我們去掉AsEnumerable,我們又回到廣場1以下錯誤:

The entity or complex type 'ModelContextName.ORDERS' cannot be constructed in a LINQ to Entities query.

我一直在這個問題了一整天掙扎,這裏是我發現了什麼。我創建了一個從我的實體類繼承的空類,並使用此類執行投影。

public sealed class ProjectedORDERS : ORDERS {} 

投影查詢(使用協方差特徵):

IQueryable<ORDERS> orders = (from order in context.ORDERS 
       select new ProjectedORDERS 
       { 
        REFERENCE = order.REFERENCE, 
        OPERATION = order.OPERATION, 
       }); 

瞧!你現在有一個預計的查詢將映射到一個實體,只有當你想要時纔會被執行。

+0

+1我也在這個問題上花了很多時間,經過一千次失敗嘗試後,才找到同樣的解決方案;空實體繼承自實體並完成它。不過,我想知道爲什麼EF不允許投影到實體類,因爲在很多情況下這會非常方便: – 2011-05-08 10:07:37