2011-08-02 23 views
87

我得到這個異常:只有初始化,實體成員和實體導航屬性都支持

指定的類型成員「付費」不支持LINQ到實體。 僅支持初始值設定項,實體成員和實體導航屬性 。

public ActionResult Index() 
    { 
     var debts = storeDB.Orders 
      .Where(o => o.Paid == false) 
      .OrderByDescending(o => o.DateCreated); 

     return View(debts); 
    } 

我的模型類

public partial class Order 
{ 
    public bool Paid { 
     get { 
      return TotalPaid >= Total; 
     } 
    } 

    public decimal TotalPaid { 
     get { 
      return Payments.Sum(p => p.Amount); 
     } 
    } 

付款是包含現場量相關的表,查詢工作,如果我刪除了Where子句顯示有關款項,任何線索有什麼錯正確信息代碼?

解決類似的回答與建議:

public ActionResult Index() 
    { 
     var debts = storeDB.Orders 
      .OrderByDescending(o => o.DateCreated) 
      .ToList() 
      .Where(o => o.Paid == false); 

     return View(debts); 
    } 
+12

答案很簡單:你不能使用LINQ到實體查詢沒有映射屬性!只有映射的屬性被轉換爲SQL。 –

回答

93

實體試圖您繳納的轉換爲SQL,並不能因爲它不是表架構的一部分。

你可以做的是讓實體查詢沒有付費過濾器的表,然後過濾掉沒有付費的過濾器。

public ActionResult Index() 
{ 
    var debts = storeDB.Orders 
     //.Where(o => o.Paid == false) 
     .OrderByDescending(o => o.DateCreated); 

    debts = debts.Where(o => o.Paid == false); 

    return View(debts); 
} 

這當然意味着您將所有數據都帶回到Web服務器並過濾其上的數據。如果要在數據庫服務器上進行篩選,則可以在表上創建計算列或使用存儲過程。

16

Linq將語句轉換爲SQL語句並將它們執行到 數據庫中。

現在,此轉換僅適用於實體成員,初始化器和實體導航屬性。 因此,要實現函數或獲取屬性比較,我們需要先將它們轉換爲內存中列表,然後應用函數來檢索數據。

因此在整體,

var debts = storeDB.Orders.toList() 
     .Where(o => o.Paid == false) 
     .OrderByDescending(o => o.DateCreated); 
+15

我建議,要求某人在訂單上做一個toList()是危險的,因爲這意味着檢索整個列表 – elgrego

+0

這對我很好,因爲我有問題的屬性在Sum Linq函數中,而不在Where子句中。所以我沒有收到不必要的數據,並且在數據被檢索到時我正在執行列表中的Linq Sum函數。謝謝!最初看起來不好的東西在某些情況下會非常有幫助! –

21

就必須解決類似的問題。 上面的解決方案需要在內存中處理,這是一個不好的做法(延遲加載)。

我的解決辦法是寫一個返回謂詞一個幫手:

public static class Extensions 
{ 
    public static Expression<Func<Order, bool>> IsPaid() 
    { 
     return order => order.Payments.Sum(p => p.Amount) >= order.Total; 
    } 
} 

你可以重寫你的LINQ語句:當你想重用計算邏輯

var debts = storeDB.Orders 
        .Where(Extensions.IsPaid()) 
        .OrderByDescending(o => o.DateCreated); 

這是非常方便(幹)。 缺點是邏輯不在你的領域模型中。

+1

有許多庫嘗試使這種方法更「內置」,請參閱:http://stackoverflow.com/a/27383641/470183。 Linq-to-entities僅限於使用「規範函數」的表達式 - 可以轉換爲SQL。 C#6引入了「表達體函數」,但這些不是真正的lambda函數(請參閱:http://stackoverflow.com/a/28411444/470183)。儘管如此,在框架中這樣做會很好,因此WIBNI https://data.uservoice.com/forums/72025-entity-framework-feature-suggestions/suggestions/15087837-support-c-6-expression-bodied- function-members-in –

+1

謝謝你這個簡單而簡潔的例子'Expression >'。我曾經理解過,但現在看起來很明顯。 – AlexB

8

另一個可能的原因是因爲你使用IEnumerable爲你的財產,而不是ICollection

所以不是:

public class This 
{ 
    public long Id { get; set; } 
    //... 
    public virtual IEnumerable<That> Thats { get; set; } 
} 

這樣做:

public class This 
{ 
    public long Id { get; set; } 
    //... 
    public virtual ICollection<That> Thats { get; set; } 
} 

而你hunky dory ...愚蠢的東西,失去2小時過去...

11

T他的問題也可能來自於在數據庫模型和視圖模型中具有相同名稱的[NotMapped]屬性。

AutoMapper嘗試在投影期間從DB中選擇它;並且NotMapped屬性顯然不存在於數據庫中。

當從數據庫模型映射到查看模型時,解決方案是Ignore AutoMapper配置中的屬性。

  1. 在您的數據庫模型中查找名爲Foo[NotMapped]屬性。
  2. 在您的View Model中查找同名的房產Foo
  3. 如果是這樣的話,那麼改變你的AutoMapper配置。添加.ForMember(a => a.Foo, b => b.Ignore());
-1

我面對這個問題,因爲在和只getwithout set屬性的成員變量

這意味着它的auto calculatednot storedthe table

因此

not existtable schema

所以make sure任何成員變量not auto calculatedhave一個gettersetter性能

相關問題