IEnumerable<int> products = new List<int> {2, 3};
IEnumerable<OrderProduct> orderProducts = new List<OrderProduct>
{
new OrderProduct(1, 1),
new OrderProduct(2, 2),
new OrderProduct(3, 4),
new OrderProduct(3, 5),
new OrderProduct(4, 5),
new OrderProduct(4, 2),
new OrderProduct(5, 2),
new OrderProduct(5, 3),
};
var orders =
(from op in orderProducts
group op by op.OrderId into orderGroup
//magic goes there
where !products.Except(orderGroup.Select(x => x.ProductId)).Any()
select orderGroup);
//outputs 5
orders.Select(x => x.Key).ToList().ForEach(Console.WriteLine);
Или у вас может быть другая версия, указанная в другом ответе, просто замените
where !products.Except(orderGroup.Select(x => x.ProductId)).Any()
на
where products.All(pid => orderGroup.Any(op => op.ProductId == pid))
, вторая будет иметь ~ 15% лучшую производительность (Iпроверил это)
Редактировать
Согласно последнему изменению требования, вам нужны заказы, которые содержат не все идентификаторы товаров, которые вы ищете, а именно те и только теproductIds, я написал обновленную версию:
var orders =
(from op in orderProducts
group op by op.OrderId into orderGroup
//this line was added
where orderGroup.Count() == products.Count()
where !products.Except(orderGroup.Select(x => x.ProductId)).Any()
select orderGroup);
Так что единственное, что вам нужно, это добавить предварительное условие, гарантирующее, что коллекции содержат одинаковое количество элементов, это будет работать для обоих предыдущие запросы, и в качестве бонуса я предлагаю 3-й вариант наиболее важного условия:
where orderGroup.Select(x => x.ProductId).Intersect(products).Count() == orderGroup.Count()