ARTICLE AD BOX
If you aren't concerned with state from the previously loaded set, then just have EF load the data from the database and consider discarding the first incomplete set for the complete one.
var newObjects = context.Examples .Select(e => new Example { Id = e.Id, A = e.A, B = e.B, C = e.C }).ToList();You're needing to go to the database anyways to fetch the expanded state so you save nothing and are adding complexity to try and avoid re-reading the "A" property etc. that was read in the first place. When you have a projection class, or an entity, you should consider always fully filling it out rather than trying to overly optimize or reuse a class across different concerns where sometimes properties are loaded and other times they aren't. When an object representation of data is passed around, it should always be assumed to be complete where if a property isn't set it is because the data state for that property is null/default.
In a case where you have 2 distinct DTOs/ViewModels like:
class ExampleSummary { public int Id { get; set; } public int A { get; set; } } class ExampleFull { public int Id { get; set; } public int A { get; set; } public int B { get; set; } }... sourced from the same table and you have loaded a set of Example1's including changes to properties that you want to override the data read when reading Example2s:
// Initial set loaded.. var objects = context.Examples .Select(e => new ExampleSummary { Id = e.Id, A = e.A }).ToList(); // Later there may be changes to objects.A values so when we load the new ExampleFull from the same table: var expandedObjects = context.Examples .Select(e => new ExampleFull { Id = e.Id, A = e.A, B = e.B, }).ToList();Now to copy across any "A" values from the original summary set to the newly loaded expandedObjects:
var matches = expandedObjects.Join(objects, a=> a.Id, b=> b.Id, (a,b) => new { Expanded = a, Summary = b }).ToList(); foreach (var match in matches) match.Expanded.A = match.Summary.A;This takes the two sets, the original set that may be modified, and the freshly loaded expanded set, joins them on the Id, then goes through each match in the set, copying the value from the original row into our expanded object property.
The advantage of this approach is that it handles cases where rows might have been added or removed between the two sets being read. If the second expanded read includes a row that wasn't in the original set, we still have the in-database value. If the original list had a row that has been deleted or otherwise not read (due to a .Where() clause etc) then there is no value to copy across. The Joined "matches" is just reference pointers so it's not creating copies of the items in the two collections.
