LINQ查询 - 多个基于int数组的多个子查询

时间:2010-07-27 12:13:31

标签: c# linq

我有一个sql查询,它执行我之后选择的类型:

select * from Products p where p.ProductId in (
    select distinct ProductId from ProductFacets 
    where ProductId in (select ProductId from ProductFacets where FacetTypeId = 1)
    and ProductId in (select ProductId from ProductFacets where FacetTypeId = 4)
)

可以将多个FacetTypeIds传递到此查询中。

此查询是在基于int []类型的参数参数的方法中构造的。

public IEnumerable<Product> GetProductsByFacetTypes(string productTypeSysName, int[] facetTypeIds)

我正在尝试研究如何在LINQ中实现这一目标。到目前为止,我想出了类似的东西:

var products = from p in sc.Products
where p.ProductType.SysName == productTypeSysName
where p.FacetTypes.Any(x => x.FacetTypeId == 1)
where p.FacetTypes.Any(x => x.FacetTypeId == 4)
select p;

返回正确的结果集。

但是我不确定如何使用int [] facetTypeIds参数构建此查询。

编辑:

ProductFacets包含以下数据:

ProductId, FacetTypeId
1, 1
1, 2
2, 1
2, 3
3, 4
3, 5
4, 1
4, 2

例如,我希望能够只选择FacetTypeId为1和2的产品。 结果集应包含ProductIds 1和4

3 个答案:

答案 0 :(得分:3)

可以通过调用Contains:

将本地集合传输到数据库
from ft in facetTypes
where facetTypeIds.Contains(ft.FacetTypeId)
select ft;

本地集合被转换为sql参数。 Sql Server的参数限制为~2100,所以要小心。


具有任何方面的产品

from p in sc.Products
where p.ProductType.SysName == productTypeSysName
where 
(
  from ft in p.FacetTypes
  where facetTypeIds.Contains(ft.FacetTypeId)
  select ft
).Any()
select p;

具有各方面的产品。

int facetCount = facetTypeIds.Count();

from p in sc.Products
where p.ProductType.SysName == productTypeSysName
where 
(
  from ft in p.FacetTypes
  where facetTypeIds.Contains(ft.FacetTypeId)
  select ft.FacetTypeId
).Distinct().Count() == facetCount
select p;

答案 1 :(得分:1)

编辑:抱歉,我误解了这个问题。如果您需要存在所有类型,我建议您使用PredicateBuilder并动态构建Where子句。这将直接使用扩展方法。

var facetTypeIds = new [] { 1, 4, ... };
var predicate = PredicateBuilder.True<Product>();
foreach (int id in facetTypeIds)
{
    int facetId = id; // avoid capturing loop variable
    predicate = predicate.And( p => p.FacetTypes.Any( x => x.FacetTypeId == facetId );
}

var products = sc.Products
                 .Where( p => p.ProductType.SysName == productTypeSysName )
                 .Where( predicate );

原文(错误,但留给上下文):

您想使用Contains。另请注意,您可以使用逻辑并将多个Where子句替换为单个Where子句。

var facetTypeIds = new [] { 1, 4, ... };

var products = from p in sc.Products
where p.ProductType.SysName == productTypeSysName
      &&  p.FacetTypes.Any( x => facetTypeIds.Contains( x.FacetTypeId ) )
select p;

答案 2 :(得分:0)

这是基于tvanfosson的代码。我对这种方法的表现有疑问。

var facetTypeIds = new [] { 1, 4, ... };

var products = from p in sc.Products
where p.ProductType.SysName == productTypeSysName
      && facetTypeIds.All(ft => p.FacetTypes.Any(x => x.FacetTypeId == ft))
select p;