2012-03-05 97 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