查询子集合 - 包含在列表中的多数互生ID

时间:2016-10-13 20:46:56

标签: linq linq-to-entities intersection

考虑以下列表:

List<long> listOfIDs = new List<long> { 1, 2, 3, 4 };
  

[(产品)1 Pineapple - (供应商)Fruit Inc / Marketplace Inc]&gt;

     

[2 Strawberry - Fruit Inc]&gt;

     

[3 Coke - Super Drinks Inc / Marketplace Inc]&gt;

     

[4 Orange Juice - Super Drinks Inc]

db.Table.Where(a => a.SubTable.All(b => listOfIds.Contains(b.SubTableId)))

虽然我选择了产品1和产品2,但我应该只将Fruit Inc作为供应商。当我将可口可乐纳入我的列表时,我不想再看到任何供应商,因为没有供应商同时代表这三种产品。

预期产出情景:

精选产品:1,2 预期成果:Fruit Inc

1,3 市场公司

1,2,3 的

1,3,4 的

3,4 超级饮料公司

2 个答案:

答案 0 :(得分:1)

我想我终于明白了这个问题。

所以你有两个many-to-many关系的实体:

public class Product
{
    public long Id { get; set; }
    public string Name { get; set; }
    public ICollection<Supplier> Suppliers { get; set; }
}

public class Supplier
{
    public long Id { get; set; }
    public string Name { get; set; }
    public ICollection<Product> Products { get; set; }
}

并给出一个包含产品ID的列表,您希望获得提供列表中所有产品的供应商列表。

至少有两种方法可以做到这一点:

List<long> productIds = ...;

(A)与您的尝试类似,但切换AllContains的角色:

var suppliers = db.Suppliers
    .Where(s => productIds.All(id => s.Products.Any(p => p.Id == id)))
    .ToList();

或者如果您更喜欢Contains(都生成一个和相同的SQL):

var suppliers = db.Suppliers
    .Where(s => productIds.All(id => s.Products.Select(p => p.Id).Contains(id)))
    .ToList();

(B)计算比赛次数:

var suppliers = db.Suppliers
    .Where(s => s.Products.Count(p => productIds.Contains(p.Id)) == productIds.Count)
    .ToList();

我不能说哪一个更好的性能,但它们产生了所需的结果并得到了LINQ to Entities的支持。

答案 1 :(得分:0)

您的问题取决于某个供应商可以拥有更多与之相关的产品,而不是您的过滤器列表中包含的产品。

您应该只需要交换数据源容器来解决此问题,以便在linq查询中测试您的条件:

a

您也可以这样方式阅读此查询:

  

获取所有的所有供应商(b记录)   listOfIds 中包含的产品(a.SubTable元素)也必须包含在内   在与每个供应商相关的产品列表中包含contacts)。