2012-03-05 33 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) 

この参加:あなたがwhere句に参加移動した場合

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

は、それが動作するはずですなぜなら、ブランドのカテゴリーを他のものに使用しているようには見えないからです。これは効果がありますか?

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

'p.ProductCategories.Whereのpcから(pc => pc.CategoryId == categoryId)'はSQLでCROSS JOINを生成しますが、答えのwhere句は生成しません。 –