如何解决Linq:使用多个嵌套组获取内部对象的小计
我需要从从SQL存储过程检索的数据集中创建一些报告。这是数据的表示形式:
+--------------+-------------------+-----------------+--------------------+
| CustomerName | CustInventoryAcct | ProductCategory | ProductSubCategory |
+--------------+-------------------+-----------------+--------------------+
| ABC | 12345 | Books | Fiction |
| ABC | 12345 | Books | Fiction |
| ABC | 12345 | Books | Non-Fiction |
| ABC | 67890 | Magazines | Sports |
+--------------+-------------------+-----------------+--------------------+
数据集还包括许多与我为简洁起见省略的实际产品相关的数据字段-以上是我需要分组的四个条件。
报告需要对这四个字段中的每个字段进行分组,因此使用上表,输出将如下所示:
Customer Header: ABC
Inventory Header: 12345
Category Header: Books
Sub Category Header: Fiction
Detail rows for each of the items in this group (2 using the sample data above)
Sub Category Footer: Fiction (Item Count : 2)
Sub Category Header: Non-Fiction
Detail row
Sub Category Footer: Non Fiction (Item Count: 1)
Category Footer: Books (Item Count: 3)
Inventory Footer: 12345 (Item Count: 3)
Inventory Header: 67890
Category Header: Magazines
Sub Category Header: Sports
Detail row
Sub Category Footer: Sports (Item Count: 1)
Category Footer: Magazines (Item Count: 1)
Inventory Footer: 67890 (Item Count: 1)
Customer Footer: ABC (Item Count: 4)
我有一个用于分组的Linq查询(不确定这是否是最好的方法):
var groupedData = rawData
.GroupBy(x => new { x.ProductSubCategory,x.ProductCategory,x.CustInventoryAcct,x.Customer })
.GroupBy(x => new { x.Key.ProductCategory,x.Key.CustInventoryAcct,x.Key.Customer })
.GroupBy(x => new { x.Key.CustInventoryAcct,x.Key.Customer })
.GroupBy(x => new { x.Key.Customer })
我使用嵌套的foreach
循环来构建报告结构:
foreach (var customer in groupedData)
{
GenerateHeader(customer.Key);
foreach (var custInventory in customer)
{
GenerateHeader(custInventory.Key.CustInventoryAcct);
foreach(var category in custInventory)
{
GenerateHeader(category.Key.ProductCategory);
foreach(var subCategory in category)
{
GenerateHeader(subCategory.Key.ProductSubCategory);
foreach (var item in subCategory)
// Populate detail rows
// Generate footer
}
// Generate footer
}
// Generate footer
}
// Generate footer
}
// Generate footer
这部分工作得很好-问题是当我尝试获取每个页脚的项目计数时。我可以使用Count()
来获得上一个嵌套级别(SubCategory)的项目计数,但是如果我尝试在更高的级别上进行操作,则可以预测地获得该级别的组数,而不是底部的基础项目层次结构。我不知道如何向下钻取,因此可以为每个嵌套级别创建小计。
我可以通过使用一些int
计数器来解决这个问题,但是我想知道Linq中是否有办法做到这一点。我遇到的困难使我怀疑我的分组查询是否不是处理Linq中嵌套组的正确方法。
我已经阅读了很多有关使用GroupBy
的SO解答和文章,但仍然无法弄清楚-有人可以帮助我了解完成我要完成的工作的最佳方法吗?
解决方法
尝试以下操作:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication169
{
class Program
{
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("CustomerName",typeof(string));
dt.Columns.Add("CustInventoryAcct",typeof(string));
dt.Columns.Add("ProductCategory",typeof(string));
dt.Columns.Add("ProductSubCategory",typeof(string));
dt.Rows.Add(new object[] { "ABC","12345","Books","Fiction" });
dt.Rows.Add(new object[] { "ABC","Non-Fiction" });
dt.Rows.Add(new object[] { "ABC","67890","Magazines","Sports" });
foreach(var name in dt.AsEnumerable().GroupBy(x => x.Field<string>("CustomerName")))
{
Console.WriteLine("Customer Header: {0}",name.Key);
foreach (var header in name.GroupBy(x => x.Field<string>("CustInventoryAcct")))
{
Console.WriteLine(" Inventory Header: {0}",header.Key);
foreach (var category in name.GroupBy(x => x.Field<string>("ProductCategory")))
{
Console.WriteLine(" Category Header: {0}",category.Key);
foreach (var subCategory in name.GroupBy(x => x.Field<string>("ProductSubCategory")))
{
Console.WriteLine(" Sub Category Header: {0}",subCategory.Key);
foreach (DataRow row in subCategory)
{
}
Console.WriteLine(" Sub Category Footer: {0}",subCategory.Key);
}
Console.WriteLine(" Category Footer: {0}",category.Key);
}
Console.WriteLine(" Inventory Footer: {0}",header.Key);
}
Console.WriteLine("Customer Footer: {0}",name.Key);
}
Console.ReadLine();
}
}
}
,
我建议您不要先进行Group
的四个级别的操作,而要逐步进行。这样,您可以Count()
每个组为您提供总计:
foreach(var customer in rawData.GroupBy(x => new { x.ProductSubCategory,x.ProductCategory,x.CustInventoryAcct,x.CustomerName }))
{
Console.WriteLine(customer.Key.CustomerName);
foreach(var inventory in customer.GroupBy(x => new { x.ProductCategory,x.CustomerName }))
{
Console.WriteLine($"\t{inventory.Key.CustInventoryAcct}");
foreach(var category in inventory.GroupBy(x => new { x.CustInventoryAcct,x.CustomerName }) )
{
// etc
}
Console.WriteLine($"\tNumber of items: {inventory.Count()}");
}
Console.WriteLine($"Number of items: {customer.Count()}");
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。