2011-10-05 63 views
0

我試圖通過將大量模型實體包裝到單個視圖模型實體中來創建SelectList在選擇列表中使用視圖模型時出現Linq to Entities錯誤

我有一個視圖模型類:

public class ReferenceDocumentSelectionViewModel 
{ 
    public ReferenceDocument Document { get; set; } 

    public int ID { get { return Document.ID; } } 

    public String DisplayText 
    { 
     get 
     { 
      return Document.DocumentNumber + 
        Document.Version + 
        Document.Revision + 
        Document.Sheet; 
     } 
    } 
} 

然後我試圖使用拉姆達expressesions創建這些對象的列表:它們分配到SelectList

var docs = _db.ReferenceDocuments 
       .Select(r => new ReferenceDocumentSelectionViewModel() 
       { 
        Document = r 
       }); 

ReferenceDocList = new SelectList(docs.OrderBy(r => r.DisplayText), 
            "ID", 
            "DisplayText"); 

在我看來,我像這樣訪問SelectList:

@Html.DropDownListFor(model => model.SelectedReferenceDoc, 
         Model.ReferenceDocList, 
         "-Select-", 
         new { id = "ReferenceList" }) 

其中model.SelectedReferenceDoc是另一視圖模型上的整數屬性。

我想這會工作,而是我發現了以下錯誤:

The specified type member 'DisplayText' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.

幫助?

編輯:在進一步調查,它似乎是導致此問題的docs.OrderBy(r => r.DisplayText)。如果我刪除它,它工作正常。任何想法爲什麼這是不被允許的?

回答

3

由於DisplayText不是映射屬性,EF不知道如何將其轉換爲SQL。這就是爲什麼它給你一個錯誤。

您可以使用LINQ到對象先裝入這裏排序的所有元素

var docs = _db.ReferenceDocuments 
       .Select(r => new ReferenceDocumentSelectionViewModel() 
       { 
        Document = r 
       }).ToList(); 

然後在內存

ReferenceDocList = new SelectList(docs.OrderBy(r => r.DisplayText), 
            "ID", 
            "DisplayText"); 

排序或按每個屬性進行排序

var docs = _db.ReferenceDocuments 
       .OrderBy(r => r.DocumentNumber) 
       .ThenBy(r => r.Version) 
       .ThenBy(r => r.Revision) 
       .ThenBy(r => r.Sheet) 
       .Select(r => new ReferenceDocumentSelectionViewModel() 
       { 
        Document = r 
       }); 

ReferenceDocList = new SelectList(docs, 
            "ID", 
            "DisplayText"); 

這種方式排序將在數據庫中完成,比在內存中進行排序要有效得多。

因此,第二個選項是首選。

+0

另一種選擇是.AsEnumerable() – MerickOWA

+0

非常好,謝謝你的解決方案!你能解釋爲什麼這是做到這一點的方法嗎?哪一個會更有效率,第一個選項還是第二個選項? – link664

+3

其必要的原因是因爲傳遞給DropDownListFor的數據仍然是IQueryable。在該上下文中完成的任何排序都會嘗試轉換爲SQL。因此,通過'DisplayText'進行排序將不起作用,因爲該值僅通過C#代碼派生。僅通過數據庫列進行排序是一種解決方法,或者通過「AsEnumerable」轉換爲簡單的「IEnumerable」是另一種方法(後者允許CLR對數據進行排序而不是數據庫)。 – Jacob