2013-08-20 104 views
0

我是EF和LINQ的初學者,我想根據產品ID檢索類別列表(帶過濾器)。EF:如何解決多對多關係(涉及一些過濾)

所以,我有Product * <---> * Category之間的許多一對多的關係,我用下面的代碼:

var categList = dbContext.Products 
       .Where(prod => prod.PROD_UID == 1234) 
       .SelectMany(prod => prod.Categories) 
       .Distinct(); 

categList = SearchCategories(filter, categList); 
categList = SortCategories(filter, categList); 
categList = PageCategories(filter, categList); 

其中SearchCategories用於重複使用一些代碼,看起來像下面

IQueryable<Category> SearchCategories(MyFilter filter, IQueryable<Category> source = null) 
{ 
    source = source ?? this.dbContext.Categories; 

    return source.Where(cat => [...filtering...]); 
} 

雖然這看起來沒問題,我想稍微優化一下,在SelectMany(使用SelectMany內部的SearchCategories)內部進行篩選...但我無法使其工作。我試過,但給我錯誤

var categList = dbContext.Products 
       .Where(prod => prod.PROD_UID == 1234) 
       .SelectMany(cat => SearchCategories(filter, prod.Categories.AsQueryable()).AsEnumerable()); 

// throws LINQ to Entities does not recognize the method 'SearchCategories' 

我怎麼能過濾SelectMany裏面的類別?

謝謝!

+0

我認爲你的代碼中有一個你不能擁有的錯字.SelectMany(cat => prod.Categories)你應該有.SelectMany(prod => prod.Categories)。 –

+0

對,它是固定的! – Learner

回答

1

你的問題是你是服務器查詢與客戶端查詢混淆,這裏沒有什麼魔力。

您的第一個查詢,直到Distinct序列化併發送到服務器,然後服務器發送一個響應,然後您在客戶端運行一個過濾器。

當你把SearchCategories在服務器查詢它不能被解析器,所以你得到的錯誤。

你這裏有兩種選擇:

1:只寫從SearchCategories在第一個查詢的所有查詢使得它在服務器

.SelectMany(prod => prod.Categories.Where(c => [...filtering...])) 

記得過濾着調用客戶端代碼運行。

2:你把一個ToList或ToArray,然後使用SearchCategories,但這個選項不會優化任何東西。

+0

爲了得到這個權利...我創建''''功能的想法是重用過濾代碼。一般來說,創建lambda表達式時我應該忘記這一點嗎? – Learner

+0

也許我必須找到一種方法來創建一個'表達式'來重用代碼,但我對這個初學者很感興趣 – Learner