我有以下代码:
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)
这是设计的吗?
问题是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)