我知道在SO和其他地方有一些brazillion LINQ嵌套查询示例,但它对我来说没有意义。如果有人可以解释这个就像我五岁那样,我会非常感激。这都是伪模糊的,所以请耐心等待这个人为的例子。
我有一个具有以下功能的EF模型:
public class Car(){
public String Vin {get; private set;}
public string Type {get; private set;}
public List<Option> Options {get; set;}
}
public class Option(){
public string Name { get; set; }
}
我从存储库中获取了IQueryable<Car> cars
的集合。
足够简单。目标是:
所以列表看起来像:
你可能会明白这个想法。我知道我可以按类型对汽车进行分组,如下所示:
from c in cars
group by c.Type into g
但我认为我需要做的是将Vin
分组到Option
并将结果分组到Type中。我也认为我可能需要
cars.SelectMany(c => c.Options)
.Select(o => o.Name)
.Distinct();
获取唯一选项名称的列表,但我不确定a)这是最有效的方法,以及b)如何将其合并到我的分组查询中。我真的不明白如何编写嵌套分组查询来实现这一点 - 第一组是外部组还是内部组?
我对此的理解低于补救,所以请再次:解释,就像我五岁。
感谢所有人。
答案 0 :(得分:2)
这肯定不是一个微不足道的问题。
我会这样做:
cars.SelectMany(c => c.Options.Select(o => new { Car = c, Option = o.Name }))
.GroupBy(x => x.Car.Type)
.Select(x => new
{
Type = x.Key,
Options = x.GroupBy(y => y.Option, y => y.Car.Vin)
.Select(y => new { Option = y.Key,
Cars = y.ToList() } )
});
此查询执行以下操作:
我们更改了我们工作的数据,以便更容易处理:您希望在汽车上方拥有选项。这意味着最终结果会让每辆车都有多种选择,所以我们真正需要的是一个(Option,Car)元组列表。
我们用
实现这一目标cars.SelectMany(c => c.Options.Select(o => new { Car = c, Option = o.Name }))
这基本上说:对于每辆车和每个选项,选择一个新的匿名类型与汽车和选项名称作为属性。我们将其命名为匿名类型Ano1。
结果将是IEnumerable<Ano1>
。
此平面数据现在按车型分组。这意味着对于每种车型,我们都有一个Ano1实例列表。因此,我们现在有一个组列表,每个组都有一个Ano1实例列表。
在这个组列表中,我们发出一个选择。对于每个组(=汽车类型),选择返回一个新的匿名类型,其中包含汽车类型的属性 - 这样信息不会丢失 - 以及选项的属性。
上一步中的选项最终将是具有Option和Cars属性的匿名类型列表。为了获得这些数据,我们通过Option对我们的所有Ano1实例进行分组,并选择汽车的VIN作为组内的元素。这些组现在转换为新的匿名类型,其中包含选项名称的属性和汽车的属性。
查询并不简单,解释也是如此。如果不清楚,请询问。
答案 1 :(得分:2)
这个linq-to-entities查询可以解决问题
var query = from c in cars
group c by c.Type into g
select new {
Type = g.Key,
Options = from o in g.Options.SelectMany(x => x.Options).Distinct()
select new {
o.Name,
Vins = from c in cars
where c.Options.Any(x => x.Name == o.Name)
where c.Type == g.Key
select c.Vin
}
}
答案 2 :(得分:2)
这不会很漂亮,我不确定L2E会处理这个问题,您可能需要从数据库中选择整个列表并在L2O中执行此操作:
var result = cars.GroupBy(c => c.Type)
.Select(c => new {
Type = c.Key,
Options = c.SelectMany(x => x.Options)
.GroupBy(x => x.Name)
.Select(x => new {
Option = x.Key ,
Vins = c.Where(y => y.Options.Any(z => z.Name == x.Key)).Select(z => z.Vin)
})
});
实例(仅限卡车建模,但适用于所有人):http://rextester.com/OGD12123