我有以下代码:
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;
}
我无法通过这种方式将sales属性设置为任何值。即使我尝试:
foreach (var item in result)
{
item.Sales = 50;
}
但是,如果我使用以下代码设置属性,它可以工作:
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 });
这是设计吗?
答案 0 :(得分: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();
然后,您的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
});
答案 1 :(得分:0)
托马斯,
您使用的var结果只是一个查询,当您迭代它时,在foreach循环中,您正在生成一个新的报表对象,但它不会“存储”在任何地方。
将ToArray()或ToList()添加到查询的末尾以解决问题:
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();
阿米尔。