C# C Linq GroupBy,获取每个组中的列列表

C# C Linq GroupBy,获取每个组中的列列表,c#,sql,linq,C#,Sql,Linq,我需要编写一个查询来获取销售的所有运输成本,并将其与估计的运输成本进行比较。我的问题是: var sales = (from sale in db.Sales where sale.DateOfSale > startDate && sale.DateOfSale < endDate group sale by new {sale.ItemID, sale.EstimatedShipping} into g

我需要编写一个查询来获取销售的所有运输成本,并将其与估计的运输成本进行比较。我的问题是:

var sales = (from sale in db.Sales
             where sale.DateOfSale > startDate && sale.DateOfSale < endDate
             group sale by new {sale.ItemID, sale.EstimatedShipping} into g
             select new
             {
                 ItemID = g.Key.ItemID
                 Estimate = g.Key.EstimatedShipping
                 ActualShipCosts = (from gSales in g select gSales.ActualShipping)
             }).ToList();

似乎对组执行任何不按键获取组的操作或执行g.Count都会使查询运行得非常慢,我无法在不超时的情况下完成此查询。在这里,我能做些什么来提高性能吗?

如果没有用于测试的所有数据库,很难判断,但这一行可能是问题所在:

(from gSales in g select gSales.ActualShipping)
请尝试以下方法:

var sales = (from sale in db.Sales
             where sale.DateOfSale > startDate && sale.DateOfSale < endDate
             group sale by new {sale.ItemID, sale.EstimatedShipping} into g
             select new
             {
                 ItemID = g.Key.ItemID,
                 Estimate = g.Key.EstimatedShipping,
                 ActualShipCosts = g.Select(gSales => gSales.ActualShipping).ToList()
             }).ToList();

这可以防止第二次失败。第一个查询可能会执行一些奇怪的连接,而使用简单的Select则不应该这样做。

我认为问题可能是由g Select gSales.ActualShipping中的from gSales引起的。Linq group by在SQL中被转换为group by,所以您不能直接访问构成group的记录。g select gSales.ActualShipping中的每个from gSales调用将执行单独的select

第一种可能的解决方案:在ItemID、EstimatedShipping对上创建索引

第二种可能的解决办法:

var sales = (from sale in db.Sales
         where sale.DateOfSale > startDate && sale.DateOfSale < endDate
         select new
         {
             ItemID = sale.ItemID
             Estimate = sale.EstimatedShipping
             ActualShipCosts = sale.ActualShipping
         }).ToList();

var groupedSales = (from sale in sales
         group sale by new {sale.ItemID, sale.EstimatedShipping} into g
         select new
         {
             ItemID = g.Key.ItemID,
             Estimate = g.Key.EstimatedShipping,
             ActualShipCosts = g.Select(gSales => gSales.ActualShipping).ToList()
         }).ToList();

这将在下载记录后脱机分组。这肯定会减少查询数量,但您必须检查数据库是否更快。

您可以在构建结果集时尝试执行实际发货选择:

var sales = db.Sales
    .Where(sale => sale.DateOfSale > startDate && sale.DateOfSale < endDate)
    .GroupBy(
        sale => new {sale.ItemID, sale.EstimatedShipping},
        sale => sale.ActualShipping)
    .ToList();

不确定,但它可能会阻止额外的枚举。

您对结果集做什么?也许有更好的方法来实现您的目标。分组前查询返回的记录估计数是多少?您是否需要实际发货成本作为列表?在分组之前,我会根据日期得到大约5万个结果。我可以跳过分组,稍后过滤大约需要10秒,但我希望找到一个更快的选项。我希望将ActualShipCosts作为列表,但将.ToList添加到ActualShipCosts查询似乎会使其成为无效查询。我想我希望在.GroupBy和.ToList之间使用.Select g=>new{g.Key,ShipCosts=g.ToList}。。。但是我得到了和以前一样的错误,Linq to Entities不识别该方法…结果是通过这些结果循环并列出。实际交付几乎不需要时间…谢谢,这正是我需要的!