Updating an item property within IEnumerable but the property doesn't stay set?
Solution 1:
IEnumerable<T>
s do not guarantee that updated values will persist across enumerations. For instance, a List
will return the same set of objects on every iteration, so if you update a property, it will be saved across iterations. However, many other implementations of IEnumerable
s return a new set of objects each time, so any changes made will not persist.
If you need to store and update the results, pull the IEnumerable<T>
down to a List<T>
using .ToList()
or project it into a new IEnumerable<T>
using .Select()
with the changes applied.
To specifically apply that to your code, it would look like this:
var transactions = (from t in db.Transactions
where t.SellingPrice != 0
select t).ToList();
var taAgents = (from ta in db.TransactionAgents
select ta).ToList();
foreach (var transaction in transactions)
{
foreach(var agent in taAgents)
{
agent.AgentCommission = ((transaction.CommissionPercent / 100) * (agent.CommissionPercent / 100) * transaction.SellingPrice) - agent.BrokerageSplit;
}
}
dataGridView1.DataSource = taAgents;
Solution 2:
Specifically, the problem is that each time you access the IEnumerable, it enumerates over the collection. In this case, the collection is a call to the database. In the first part, you're getting the values from the database and updating them. In the second part, you're getting the values from the database again and setting that as the datasource (or, pedantically, you're setting the enumerator as the datasource, and then that is getting the values from the database).
Use .ToList() or similar to keep the results in memory, and access the same collection every time.
Solution 3:
Assuming you are using LINQ to SQL, if EnableObjectTracking is false, then the objects will be constructed new every time the query is run. Otherwise, you would be getting the same object instances each time and your changes would survive. However, like others have shown, instead of having the query execute multiple times, cache the results in a list. Not only will you get what you want working, you'll have fewer database round trips.
Solution 4:
I found that I had to locate the item in the list that I wanted to modify, extract the copy, modify the copy (by incrementing its count property), remove the original from the list and add the modified copy. var x = stats.Where(d => d.word == s).FirstOrDefault(); var statCount = stats.IndexOf(x); x.count++; stats.RemoveAt(statCount); stats.Add(x);