2015-08-25 95 views
3

我要實現我的ASP.NET MVC應用程序,在這裏用戶可以選擇的商品搜索1個或多個標準高級搜索高級搜索使用Lambda表達式

比方說,我有這些標準:顏色大小價格範圍

這是據我得到到目前爲止

ProductSizeList = db.ProductSizes.Where(ProductSize => 
    (string.IsNullOrEmpty(ProductColorId) || ProductSize.Product.ProductColors.Where(a => a.ColorID == IntColorId).Any()) 
    ).GroupBy(x => x.ProductID).Select(Grouped => Grouped.FirstOrDefault()).ToList(); 

我有ProductColor表之間的許多一對多關係,ProductColor是一個聯繫起來。與ProductProductSizeSize表同樣的事情。

的代碼與Size,並且Price Range完美的工作。與Color的問題,因爲.Any()時返回找到的第一個Product。如果有多個Product,它只返回第一個。

所以,我想知道是否有另一個方法,或另一種方式能夠獲得具有指定顏色的所有產品。

我搜索了很多,並知道我可以動態構建Where Clause,但我認爲這對我的需求來說太多了。如果有一個簡單的解決方案,我會更高興。

編輯

我刪除了工作,作爲通緝代碼由@Jeroen的建議,離開了一個我想解決。

解決

我固定它,這要歸功於結合@jason和@Marlon答案。我將把解決方案放在一個單獨的答案中。我只想了解2點:

  • 爲什麼它只工作正確,當我基於我的產品查詢?
  • 爲什麼`.Distinct()`沒有做任何事情,我得到了重複的產品。
+0

你可能應該看看Predicates(https://stackoverflow.com/a/1710395/3951051)並可能鏈接它們。 (https://stackoverflow.com/questions/1248232/combine-multiple-predicates) – WhoIsJohnDoe

+1

如果你將代碼修剪到你遇到問題的實際lambda(部分),並且包含一些最小的設置代碼來重現問題。目前我覺得有很多代碼讓你分心,因爲你遇到了實際的問題。 – Jeroen

+0

我想你不是通過調用Any()來過濾你的結果,而是在這裏:Grouped.FirstOrDefault()。順便說一句,你可以直接調用任何謂詞而不使用Where子句:Any(a => a.ColorID == IntColorId) – FireAlkazar

回答

3

請試試這個。當調用ToList時,它使用IQueryable讓您在執行數據庫之前更輕鬆地構造條件。

var query = db.ProductSizes.AsQueryable(); 
if (string.IsNullOrEmpty(ProductColorId) == false) 
    query = query.Where(ProductSize => ProductSize.Product.ProductColors.Any(a => a.ColorID == IntColorId)) 
if (string.IsNullOrEmpty(SizeId) == false) 
    query = query.Where(ProductSize => ProductSize.Size.Id == IntSizeId); 
if (string.IsNullOrEmpty(From) == false) 
    query = query.Where(ProductSize => ProductSize.Price >= DecimalFrom); 
if (string.IsNullOrEmpty(To) == false) 
    query = query.Where(ProductSize => ProductSize.Price <= DecimalTo); 
var ProductSizeList = query 
    .Select(ProductSize => ProductSize.ProductID) 
    .Distinct() 
    .ToList(); 
+0

對不起,但我不明白這與我的解決方案有何不同。 '.Any()'將在條件滿足時返回,並且僅返回第一個產品。 – Ahmed

+2

只有鏈接到產品的顏色鏈接到查詢中的ProductSize時,'.Any()'此處才返回true。它尊重符合您其他條件的產品。也許這種不理想的結果是由於'GroupBy'中的'FirstOrDefault'或者From/To在原始查詢中沒有真正分離,或者因爲您有其他產品大小鏈接到您不期望匹配的產品顏色?沒有看到你的數據,很難猜測這裏有什麼問題,但這種方法應該沒問題。我用過很多次。 –

1

嘗試的基礎上查詢的產品,而不是ProductSize:(你沒有說,所以我假定尺寸和價格都在ProductSize對象)。

var query = db.Product.AsQueryable(); 
if (string.IsNullOrEmpty(ProductColorId) == false) 
    query = query.Where(product => product.ProductColors.Where(a => a.ColorID == IntColorId).Any()); 
if (string.IsNullOrEmpty(SizeId) == false) 
    query = query.Where(product => product.Sizes.Where(s => s.Size_Id == IntSizeId)); 

(...) 

var ProductSizeList = query 
    .Select(product => product.ProductID) 
    .Distinct() 
    .ToList(); 

我prefere賈森W公司的做法,而不是把一切都在一個查詢,因爲在過去的「或」在查詢中會忽略數據庫中的所有指標。

+0

對不起,但我不明白這與我的解決方案有何不同。 '.Any()'將在條件滿足時返回,並且僅返回第一個產品。 – Ahmed

+0

任何位於Product.Where內部,因此將針對每個產品調用。並且基於您對Product實體的查詢,您不需要擁有Group by。 – Marlon

0

這是爲我工作

var query = db.Products.AsQueryable(); 
if (string.IsNullOrEmpty(ProductColorId) == false) 
    query = query.Where(Product => Product.ProductColors.Any(a => a.ColorID == IntColorId)); 
if (string.IsNullOrEmpty(SizeId) == false) 
    query = query.Where(Product => Product.ProductSizes.Any(a => a.SizeID == IntSizeId)); 
if (string.IsNullOrEmpty(From) == false) 
    query = query.Where(Product => Product.ProductSizes.Any(a => a.Price >= DecimalFrom)); 
if (string.IsNullOrEmpty(To) == false) 
    query = query.Where(Product => Product.ProductSizes.Any(a => a.Price <= DecimalTo)); 
var ProductsList = query 
    .Select(ProductSize => ProductSize) 
    .GroupBy(x => x.id).Select(Grouped => Grouped.FirstOrDefault()) 
    .ToList(); 

我根據我的查詢上Product,並用GroupBy移除,而不是Distinct重複的結果。