Entity Framework 4 in Action读书笔记——第四章:使用LINQ to Entities查询:分组数据
4.3 分组数据
基本需求:根据送货城市分组返回所有订单。
解决方案:在查询中使用group ... by ...子句。
var result = from c in ctx.Orders group c by c.ShippingAddress.City;
结果类型有点复杂,因为它是IEnumerable<IGrouping<string, Order>>的对象。IGrouping是一个特殊的类,它有一个键(Key)属性,在本例中是送货地址的值,和一个值(Value)属性。值属性是一个IEnumerable<T>集合,它包含对应Key的所有对象。例如,如果Key属性的值是Miami,Value属性包含所有送货地址是这个城市的订单。
遍历这个结果需要一个对所有Key的循环和一个内循环,内循环遍历对应Key的值。
foreach (var key in result) { Console.WriteLine(key.Key); foreach (var item in key) { Console.WriteLine(item.OrderId); } }
下面更改分组数据的名称。
var result = from c in ctx.Orders group c by c.ShippingAddress.City into oGroup select new { CityName = oGroup.Key, Items = oGroup }; foreach (var key in result) { Console.WriteLine(key.CityName); foreach (var item in key.Items) { Console.WriteLine(item.OrderId); } }
前面已经提到分组键,但是我们没有解释分组键可以是什么。到目前为止,已经使用了单一的属性,但那只是可能性之一。通常,你要根据多个属性分组数据。例如,你可能想根据送货城市和邮政编码分组订单,以便更好的组织发货。在C#中,你必须使用匿名类型指定一个对象作为键,把送货城市和邮政编码放入其中。下面的代码使用了多个属性分组数据。
var result = from c in ctx.Orders group c by new { c.ShippingAddress.City, c.ShippingAddress.ZipCode }; foreach (var key in result) { Console.WriteLine(key.Key.City + "-" + key.Key.ZipCode); foreach (var item in key) { Console.WriteLine(item.OrderId); } }
正如可以自定义键值以反映你的需求,分组数据也可以使用投影以节省资源。你可以在分组的Select方法内的值列表中调用Select方法,如下:
var result = from c in ctx.Orders group c by c.ShippingAddress.City into g select new { g.Key, Items = g.Select(og => new { og.OrderId, og.OrderDate }) };
投影的力量还可以允许分组数据包含关联实体的信息。在这里就不展示如何做了,因为它跟上一篇中的相似。
LINQ to Entities甚至可以筛选分组后的数据。这就是接下来的主题。
4.3.1筛选汇总数据
筛选汇总数据等价于在SQL中使用HAVING。举个例子,你可能想搜索按城市分组的订单,订单总数高于一个给定的数字。使用LINQ聚集家族的方法很容易就可以实现这一功能。
var result = from c in ctx.Orders group c by c.ShippingAddress.City into g where g.Count() > 2 select g;
分组后面的Where子句只影响分组后的数据。如果你需要在分组之前筛选,你必须在分组之前调用Where。根据Where子句放置的位置,查询中的变量可超出范围。我们修改一下上一段代码。如果你把Where放在group by子句之前,c变量在范围之内,但是g变量不在范围之内,因为还没有声明g。相反,如果把Where子句放在group by子句之后,c变量将不在范围之内,不能被引用,而g变量在范围之内,可以使用。
现在你已经掌握了筛选,投影和分组,下面将学习LINQ to Entities的另一个功能:sorting。它是由LINQ to Entities启用的最简单的任务。当涉及到关联时情况可能有些复杂,但现在你应该感到舒服。