我对编译器如何处理以下表达式感到好奇:
var collapsed = elements.GroupBy(elm => elm.OrderIdentifier).Select(group => new ModelsBase.Laser.Element()
{
CuttingDurationInSeconds = group.Sum(itm => itm.CuttingDurationInSeconds),
FladderDurationInSeconds = group.Sum(itm => itm.FladderDurationInSeconds),
DeliveryDate = group.Min(itm => itm.DeliveryDate),
EfterFladderOpstilTid = group.First().EfterFladderOpstilTid,
EfterRadanOpstilTid = group.First().EfterRadanOpstilTid,
});
如您所见,我正在使用两次组总和,所以没有人知道“组”列表是否将被重复两次以获取两个总和,或者是否将其优化,因此实际上只有1个完整的迭代列表。
答案 0 :(得分:2)
LINQ通常不是实现高性能的最佳方法,您获得的是编程效率,无需太多行代码即可获得结果。
优化的可能性有限。对于SQL查询,有一个经验法则:一个查询胜于两个查询。
1)到SQL_Server只有一次往返
2)使SQL Server可以优化那些查询,如果服务器知道下一步要做什么,优化就会变得更好。优化是针对每个查询完成的,而不是针对多个查询。
如果使用Linq to Objects,构建庞大的查询绝对没有收益。 如您的示例所示,它可能会导致多次迭代。您可以使代码更简单,更易于阅读-但您放弃了控制权,因此放弃了性能。
答案 1 :(得分:1)
编译器当然不会对其进行优化。
如果这是使用LINQ to Objects,因此是委托,则委托将对5个属性的每个组进行5次迭代。
如果这是使用LINQ to SQL,Entity Framework或类似的东西,因此是表达式树,那么基本上取决于查询提供者来适当地优化它。
答案 2 :(得分:1)
您可以通过在分组键中添加两个字段来优化请求
var collapsed = elements.GroupBy(elm => new{
OrderIdentifier=elm.OrderIdentifier,
EfterFladderOpstilTid=elm.EfterFladderOpstilTid,
EfterRadanOpstilTid=elm.EfterRadanOpstilTid
})
.Select(group => new ModelsBase.Laser.Element()
{
CuttingDurationInSeconds = group.Sum(itm => itm.CuttingDurationInSeconds),
FladderDurationInSeconds = group.Sum(itm => itm.FladderDurationInSeconds),
DeliveryDate = group.Min(itm => itm.DeliveryDate),
EfterFladderOpstilTid = group.Key.EfterFladderOpstilTid,
EfterRadanOpstilTid = group.Key.EfterRadanOpstilTid,
});
或者通过使用LET语句
var collapsed = from groupedElement in
(from element in elements
group element by element.OrderIdentifier into g
select g)
let First = groupedElement.First()
select new ModelsBase.Laser.Element()
{
CuttingDurationInSeconds = groupedElement.Sum(itm => itm.CuttingDurationInSeconds),
FladderDurationInSeconds = groupedElement.Sum(itm => itm.FladderDurationInSeconds),
DeliveryDate = groupedElement.Min(itm => itm.DeliveryDate),
EfterFladderOpstilTid = First.EfterFladderOpstilTid,
EfterRadanOpstilTid = First.EfterRadanOpstilTid
};