LINQ条件连接

时间:2012-03-05 21:22:36

标签: linq-to-entities

有什么方法可以重写这段代码,这样我就不必在多个查询中复制joinwhere子句了吗?

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();

这两个查询之间唯一的变化是这个连接:

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

使用此联接:

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

2 个答案:

答案 0 :(得分:1)

经过一夜安眠后,我想出了解决方案,这非常简单 - 将查询拆分为两部分:

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();

答案 1 :(得分: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 };