2012-09-19 153 views
2

我需要將EF中的一些POCO實體投影到它們的縮減視圖模型表示中以傳遞給序列化程序。這種情況下的實體是裝運和申請單,並且具有0..1的關係。如果我不傳遞視圖模型,那麼它會在嘗試序列化Requisition和Shipment之間的循環引用時引發堆棧溢出異常。將嵌套實體嵌入到嵌套視圖模型中

return db.ShipmentRequisitions 
       .Include(c => c.Shipment) 
       .Select(r => new ViewModels.Requisition 
       { 
        ID = r.ID, 
        ... 
        Shipment = r.Shipment != null ? new ViewModels.Shipment 
        { 
         ID = r.Shipment.ID, 
         ... 
        } : null 
       }).AsQueryable(); 

如果貨件爲空,則在嘗試訪問r.Shipment.ID時會出現異常。我像上面添加了一個空檢查,現在得到以下異常。

無法創建類型'Api.ViewModels.Shipment'的常量值。 在此上下文中僅支持基本類型(如Int32,String和Guid) 。

這令我奇怪的,因爲它是相當愉快創建嵌套ViewModels.Shipment作爲選擇的一部分,之前我加空校驗,所以它必須有一些與此有關。

我可以在調用堆棧中看到一些EF,所以我在一個快速測試項目中嘗試了一下,只用直接的對象用純LINQ來嘗試它。

var user = users.Select(u => new ViewModel.User 
       { 
        Id = u.Id, 
        Profile = u.Profile != null ? new ViewModel.Profile 
        { 
         Id = u.Profile.Id 
        } : null 
       }).ToList(); 

令我驚訝的工作。我無法弄清楚這在第一個代碼示例中不起作用。

UPDATE

我發現,如果作爲一個選擇的一部分,我做這樣的事情:

.Select(r => new ViewModels.Requisition 
        { 
         ID = r.ID, 
         ShipmentDescription = r.Shipment.Description 
        }) 

這是有效的扁平化所需的出貨性質成一個單一的DTO。在設置Description屬性時,如果Shipment在任何記錄上爲空,我希望得到一個NullReferenceExcetion。然而它並沒有發生。 LINQ似乎抑制了這個異常,並且ShipmentDescription通過了null。它可以節省我對每個嵌套屬性進行內聯檢查。不幸的是,當創建一個嵌套的對象時,這似乎並沒有擴展到相同的東西。

+0

同樣的問題在這裏:http://stackoverflow.com/questions/10904375/can-i-project-an-optional-reference-of-an-entity-into-an-optional-reference-of-t你最後如果使用例如'ID = r.Shipment.ID'當'左側ID'的例子就是BTW失敗*在一個數據庫中的記錄不爲空的*和'Shipment'是'NULL'。 – Slauma

回答

0

的問題是這一行:

.SingleOrDefault(r => r.ID == id);

EF試圖表達r.ID == id轉換爲SQL,而不是管理。

的解決方案是簡單地改變行: .ToEnumerable().SingleOrDefault(r => r.ID == id);

這工作,因爲只有IQueryable的轉換爲SQL,不IEnumerable的。

+0

感謝您的回答。 SingleOrDefault不是必需的。我試圖做同樣的選擇上都返回單個記錄的方法,並返回一個IQueryable準備呼叫的人。在這兩種情況下,它都有相同的問題。我已更新我的問題以反映這一點。 –

1

您可以在ViewModels.Requisition納入ViewModels.Shipment對象,而空校驗如果在Shipment類的所有屬性都爲空的。雖然這有點痛苦,因爲現在Shipment對象僅在沒有裝運的情況下使用空值創建。

你也可以把它圍:選擇具有在他們Requisitions收藏Shipment模型。值得一試,如果它不會讓你的應用程序的其他部分變得太糟糕。