2012-03-05 59 views
1

有沒有什麼方法可以重寫這段代碼,以便我不必在多個查詢中複製joinwhere子句?LINQ條件連接

if (categoryId > 0) 
{ 
    query = from p in _productRepository.Table 
      from pv in p.ProductVariants.DefaultIfEmpty() 
      from pc in p.ProductCategories.Where(pc => pc.CategoryId == categoryId) 
      join psa in _productSpecificationAttributeRepository.Table on p.Id equals psa.ProductId 
      join sao in _specificationAttributeOptionRepository.Table on psa.SpecificationAttributeOptionId equals sao.Id 
      join sa in _specificationAttributeRepository.Table on sao.SpecificationAttributeId equals sa.Id 
      where p.Published && pv.Published && !p.Deleted && psa.AllowFiltering && 
      (!pv.AvailableStartDateTimeUtc.HasValue || pv.AvailableStartDateTimeUtc.Value < nowUtc) && 
      (!pv.AvailableEndDateTimeUtc.HasValue || pv.AvailableEndDateTimeUtc.Value > nowUtc) 
      select new {sa, sao}; 
} 
else if (brandId > 0) 
{ 
    query = from p in _productRepository.Table 
      from pv in p.ProductVariants.DefaultIfEmpty() 
      from pb in p.ProductBrands.Where(pb => pb.BrandId == brandId) 
      join psa in _productSpecificationAttributeRepository.Table on p.Id equals psa.ProductId 
      join sao in _specificationAttributeOptionRepository.Table on psa.SpecificationAttributeOptionId equals sao.Id 
      join sa in _specificationAttributeRepository.Table on sao.SpecificationAttributeId equals sa.Id 
      where p.Published && pv.Published && !p.Deleted && psa.AllowFiltering && 
      (!pv.AvailableStartDateTimeUtc.HasValue || pv.AvailableStartDateTimeUtc.Value < nowUtc) && 
      (!pv.AvailableEndDateTimeUtc.HasValue || pv.AvailableEndDateTimeUtc.Value > nowUtc) 
      select new {sa, sao}; 
} 

//only distinct attributes (group by ID) 
query = from x in query 
     group x by x.sao.Id into xGroup 
     orderby xGroup.Key 
     select xGroup.FirstOrDefault(); 

的2個查詢之間唯一改變的是這個連接:

from pc in p.ProductCategories.Where(pc => pc.CategoryId == categoryId) 

與此連接:

from pb in p.ProductBrands.Where(pb => pb.BrandId == brandId) 

回答

1

一個良好的夜間睡眠後,我想出了一個解決方案,這是很簡單 - 2份將查詢:

if (categoryId > 0) 
{ 
    q1 = from p in _productRepository.Table 
     from pc in p.ProductCategories.Where(pc => pc.CategoryId == categoryId) 
     select p; 
} 
else if (brandId > 0) 
{ 
    q1 = from p in _productRepository.Table 
     from pb in p.ProductBrands.Where(pb => pb.BrandId == brandId) 
     select p; 
} 
var query = from p in q1 
      from pv in p.ProductVariants.DefaultIfEmpty() 
      join psa in _productSpecificationAttributeRepository.Table on p.Id equals psa.ProductId 
      join sao in _specificationAttributeOptionRepository.Table on psa.SpecificationAttributeOptionId equals sao.Id 
      join sa in _specificationAttributeRepository.Table on sao.SpecificationAttributeId equals sa.Id 
      where p.Published && pv.Published && !p.Deleted && psa.AllowFiltering && 
      (!pv.AvailableStartDateTimeUtc.HasValue || pv.AvailableStartDateTimeUtc.Value < nowUtc) && 
      (!pv.AvailableEndDateTimeUtc.HasValue || pv.AvailableEndDateTimeUtc.Value > nowUtc) 
      select new { sa, sao }; 

//only distinct attributes (group by ID) 
query = from x in query 
     group x by x.sao.Id into xGroup 
     orderby xGroup.Key 
     select xGroup.FirstOrDefault(); 
0

,如果你移動的加入到where子句它應該工作,因爲它似乎沒有使用任何其他品牌的類別。這會工作嗎?

query = from p in _productRepository.Table 
     from pv in p.ProductVariants.DefaultIfEmpty() 
     join psa in _productSpecificationAttributeRepository.Table on p.Id equals psa.ProductId 
     join sao in _specificationAttributeOptionRepository.Table on psa.SpecificationAttributeOptionId equals sao.Id 
     join sa in _specificationAttributeRepository.Table on sao.SpecificationAttributeId equals sa.Id 
     where 
     ((categoryId > 0 && p.ProductCategories.Any(pc => pc.CategoryId == categoryId)) || 
     (brandId > 0 && p.ProductBrands.Any(pb => pb.BrandId == brandId))) && 
     p.Published && pv.Published && !p.Deleted && psa.AllowFiltering && 
     (!pv.AvailableStartDateTimeUtc.HasValue || pv.AvailableStartDateTimeUtc.Value < nowUtc) && 
     (!pv.AvailableEndDateTimeUtc.HasValue || pv.AvailableEndDateTimeUtc.Value > nowUtc) 
     select new { sa, sao }; 
+0

我不認爲這會因爲線路工作'從PC中的p.ProductCategories.Where(pc => pc.CategoryId == categoryId)'在SQL中產生一個CROSS JOIN,而你的答案中的where子句沒有。 – 2012-03-05 22:07:59