2013-04-04 173 views
2

下面的代碼搜索匹配關鍵字s或處於與關鍵字s匹配的類別下的產品。LINQ:選擇一個類別下的產品,包括子類別

這是工作但繁瑣,我想知道是否有一個更短的方法來做到這一點?

var products = context.Products.Where(x => 
       x.Name.Contains(s) || 
       x.Products_Categories.Any(pc => 
        pc.Category.Name.Contains(s) || 
        (pc.Category.Category1 != null && pc.Category.Category1.Name.Contains(s)) || 
        (pc.Category.Category1 != null && pc.Category.Category1.Category1 != null && pc.Category.Category1.Category1.Name.Contains(s) || 
        (pc.Category.Category1 != null && pc.Category.Category1.Category1 != null pc.Category.Category1.Category1.Category1 != null && &&pc.Category.Category1.Category1.Category1.Name.Contains(s)) 
       ); 

如果這不是明擺着:

Products_Categories是許多一對多的關係,一個Product可以在一個或多個Category

Category1Category的父類別。

請注意,它鏈接到數據庫,所以我不能使用像IsUnderCategory()這樣的函數。
我現在不需要表達式,因爲這段代碼只用了一次。

+1

看起來應該在數據庫中創建一個View來獲取有關類別(使用公共表表達式)的分層數據並使用該View進行查詢,而不是'Category'表本身。 – MarcinJuraszek 2013-04-04 05:50:02

回答

1

在linq中沒有任何遞歸查詢的捷徑,在linq中沒有什麼捷徑可以通過SQL查詢提供程序來支持。但是,在執行之前,有一條聲明先被轉換爲SQL :SQL沒有空引用的概念。所以,如果你的語句刪除所有null檢查:

var products = context.Products.Where(x => 
       x.Name.Contains(s) || 
       x.Products_Categories.Any(pc => 
        pc.Category.Name.Contains(s) || 
        pc.Category.Category1.Name.Contains(s) || 
        pc.Category.Category1.Category1.Name.Contains(s) || 
        pc.Category.Category1.Category1.Category1.Name.Contains(s)) 
       ); 

與許多外部聯接將轉換爲SQL語句。正如你所知道的,如果你在沒有記錄時處理外連接表的字段,SQL不會崩潰。

該查詢將是......怪異的。你必須假定層次結構的最大深度。唯一可以改進的方法是在數據庫中創建一個視圖,該視圖通過recursive SQL query返回產品的所有類別。

0

使用EF的另一種方法是使用while循環簡單查詢子類別的所有類別。

完成後,您將擁有所有ID。第一次,查詢計劃尚未完成,它需要一段時間,但它的速度非常快,取決於數據庫的怪異程度。

然後,你可以query for all products that have any of a list of category IDs使用Contains方法被翻譯成WHERE FieldName IN (1,2,3)

這種方法的優點是,它不依賴於你有子類別的多少級。它始終有效,而另一種替代方式默默無聞。

相關問題