尝试使用循环在LINQ GroupBy Select中设置属性

Tho*_*mas 1 linq

我有以下代码:

public class Report
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Sales { get; set; }
}

var result = myItems.GroupBy(x => new { Id = x.Id, Name = x.Name }).Select(x => new Report { Id = x.Key.Id, Name = x.Key.Name });

foreach (var item in result)
{
    item.Sales = anotherColletion.FirstOrDefault(x => x.Id == item.Id).Sales;
}
Run Code Online (Sandbox Code Playgroud)

我无法通过这种方式将sales属性设置为任何值.即使我尝试:

foreach (var item in result)
{
    item.Sales = 50;
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我使用以下代码设置属性,它可以工作:

var result = myItems.GroupBy(x => new { Id = x.Id, Name = x.Name }).Select(x => new Report { Id = x.Key.Id, Name = x.Key.Name, Sales = 50 });
Run Code Online (Sandbox Code Playgroud)

这是设计的吗?

Ani*_*Ani 5

问题是LINQ查询是懒惰的("延迟执行").您正在foreach循环中为查询的每个结果设置属性,但这些结果基本上会消失在空气中.当您(在尚未向我们展示)之后再次枚举查询结果时,将重新执行foreach查询并重新创建结果,从而有效地撤消更改.请记住,查询只是如何生成结果的规范,而不是结果本身.

一个简单的解决方法是物化查询第一到一个集合.

var result = myItems.GroupBy(x => new { Id = x.Id, Name = x.Name })
                    .Select(x => new Report { Id = x.Key.Id, Name = x.Key.Name })
                    .ToList();
Run Code Online (Sandbox Code Playgroud)

foreach然后,您将最终改变内存中集合的元素而不是惰性查询的结果,因此将在下游可见.

但就个人而言,请考虑在查询中设置属性:

var result = myItems.GroupBy(x => new { Id = x.Id, Name = x.Name })
                    .Select(x => new Report
                                 { 
                                   Id = x.Key.Id,
                                   Name = x.Key.Name,
                                   Sales = anotherCollection.First(a => a.Id == x.KeyId)
                                                            .Sales
                                  });
Run Code Online (Sandbox Code Playgroud)