I have the following code:
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;
}
I am unable to set the sales property to any value this way. Even if I try:
foreach (var item in result)
{
item.Sales = 50;
}
However, if I set the property using the following code it works:
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 });
Is this by design?
The problem is that LINQ queries are lazy (“deferred execution”). You are setting the property on each result of the query in the
foreachloop, but these results will essentially disappear into thin air.When you enumerate the results of the query again after your
foreach(which you haven’t shown us), the query is re-executed and the results recreated, effectively undoing your changes. Remember that the query is just a specification for how to produce the results, not the results themselves.A simple fix is to materialize the query into a collection first.
Your
foreachwill then end up mutating the elements of an in-memory collection rather than the results of a lazy query, and will therefore be visible downstream.Personally though, consider setting the property in the query itself: