2014-09-02 144 views
5

我想鞏固使用實體框架訪問不同表的邏輯。我創建了從我的註冊主體拉動所有登記在該人正在參加一個擴展方法:我可以在Entity Framework SubQuery中使用擴展方法嗎?

public static IEnumerable<Registration> Attending(this IEnumerable<Registration> registrations) 
{ 
    return registrations.Where(r => r.Status == RegistrationStatus.Paid || r.Status == RegistrationStatus.Assigned || r.Status == RegistrationStatus.Completed); 
} 

這對於這樣的疑問的偉大工程:

var attendees = db.Registrations.Attending().ToList(); 

但在使用時,它不工作子查詢:

ProductTotals = db.Products.Where(p => p.EventID == ev.Id).Select(p => new ProductSummaryViewModel 
{ 
    ProductID = p.ProductID, 
    ProductName = p.Name, 
    Registrations = p.Registrations.Attending().Count(), 
}).ToList(); 

我得到以下錯誤:

LINQ to Entities does not recognize the method 'System.Collections.Generic.IEnumerable 1[Registration] Attending(System.Collections.Generic.IEnumerable 1[Registration])' method, and this method cannot be translated into a store expression.

是否有任何方式在子查詢中重用該代碼?

+0

您可以在'Select'之前使用'AsEnumerable()'在內存中執行操作。儘管您失去了在數據庫級別執行它的優勢。 – Shoe 2014-09-02 13:24:47

+2

如果您在EF查詢中使用該方法,則該方法應該接受並返回'IQueryable'而不是'IEnumerable',否則查詢不會在數據庫上執行。 – Servy 2014-09-02 14:02:55

+0

@Servy謝謝,我注意到同樣的事情,並改變了使用IQueryable – Austin 2014-09-02 17:35:41

回答

8

您嘗試實現的主要目標是重複使用定義Attending的含義的謂詞。你可以通過將表達式存儲在一個只讀變量中來實現這一點,任何需要它的應用程序都可以使用該變量,例如在靜態類ExpressionConstants中。

public static readonly Expression<Func<Registration, bool>> IsAttending = 
    r => r.Status == RegistrationStatus.Paid 
     || r.Status == RegistrationStatus.Assigned 
     || r.Status == RegistrationStatus.Completed; 

然後,你可以做

var attendees = db.Registrations.Where(ExpressionConstants.IsAttending).ToList(); 

而在子查詢中使用:

ProductTotals = db.Products.Where(p => p.EventID == ev.Id).Select(p => new ProductSummaryViewModel 
{ 
    ProductID = p.ProductID, 
    ProductName = p.Name, 
    Registrations = p.Registrations.AsQueryable() // AsQueryable() 
        .Where(ExpressionConstants.IsAttending).Count(), 
}) 

AsQueryable()是必要的,因爲p.Registrations可能是一個ICollection

相關問題