Reputation: 369
Hi have a list of object and each object has another list items respectively. I want to update a property in a sub list after checking a condition. I have tried a linq query but it doesn't update the property. Please help me
int priceBookId = 1;
foreach (var store in stores)
{
store.SelectedBooks.Where(d => d.BookID == priceBookId ).Select(x => {x.IsPriceBook = true; return x; });
}
Each stores has selected book list and each book has its own properties. Here what I want is to update IsPriceBook property when selected book is a pricebook
Upvotes: 0
Views: 2839
Reputation: 2540
Select()
does not work because that creates a projection that does nothing until you .ToList()
it (then it will perform the update). But that's just using Select
in the way it's not intended.
You can try ForEach
, which loops through the original list, like this:
int priceBookId = 1;
foreach (var store in stores)
{
store.SelectedBooks.Where(d => d.BookID == priceBookId).ToList().ForEach(x => x.IsPriceBook = true);
}
That's the quickest solution.
Upvotes: 0
Reputation: 100555
The code in the post demonstrates why doing updates of objects in .Select
(or other LINQ methods) is bad idea:
Problem with original code - Where
and Select
are lazily evaluated and hence nothing requests enumeration of the result no evaluation actually happens. To fix - forcing iteration would work. Use .ToList()
or .All(...)
as shown in Query and updating a property in a collection using LINQ.
foreach (var store in stores)
{
store.SelectedBooks
.Where(d => d.BookID == priceBookId )
.Select(x => {x.IsPriceBook = true; return 42; }) // return anything
.ToList(); // force iteration with `ToList`
}
You can even remove outer foreach
stores.SelectMany(r =>r.SelectedBooks)
.Where(d => d.BookID == priceBookId )
.All(x => {x.IsPriceBook = true; return true; }); // force iteration with All
Indeed fixing code that way will be consider as "hack" and really you should first select item and that act on them:
foreach (var book in
stores.SelectMany(store => store.SelectedBooks)
.Where(d => d.BookID == priceBookId ))
{
book.IsPriceBook = true;
}
Upvotes: 1
Reputation: 306
select will create new object with updated properties, so if you make like:
var updatedProperties = store.SelectedBooks.Where(d => d.BookID == priceBookId ).Select(x => {x.IsPriceBook = true; return x; });
you will get the result in updatedProperties variable. in your case. you can update property if you use 2 cycles, something like the following:
foreach (var store in stores)
{
foreach (var selectedBook in store.SelectedBooks.Where(d => d.BookID == priceBookId))
{
selectedBook.IsPriceBook = true;
}
}
since store.SelectedBooks has reference type, selectedBook.IsPriceBook = true; will update value by reference.
Upvotes: 0