I have this situation: I have a MasterPlanComponent object that holds multiple objectives. These objectives hold multiple targets.
Upon creating a masterPlanComponent (with 2 objectives) we create 4 targets for both of those objectives.
This is what that's supposed to look like:
The problem with the below code is that only one set of 4 targets are created, and only for the second objective.
public async Task<MasterPlanComponent> CreateMasterPlanComponent(int masterPlanId, CreateMasterPlanComponentCommand command)
{
var masterPlan = await _context.MasterPlans
.Include(mp => mp.Components)
.Include(mp => mp.Objectives)
.SingleOrDefaultAsync(m => m.MasterPlanId == masterPlanId);
var targets = new List<ObjectiveNetTarget>();
//creating new targets and setting two of their fields
for (int i = 0 ; i < 4 ; i++)
{
targets.Add(new ObjectiveNetTarget
{
CustomerMarketSegment = command.Scope.CustomerMarketSegment,
OrganizationUnit = new OrganizationUnitRef
{
Name = "Sales",
Code = "1251"
}
});
}
var masterPlanComponent = Mapper.Map<CreateMasterPlanComponentCommand, MasterPlanComponent>(command);
foreach (var objective in masterPlanComponent.Objectives)
{
objective.TargetValues = new List<ObjectiveNetTarget>(targets);
}
masterPlanComponent.Status = MasterPlanComponentStatuses.New;
masterPlan.Components.Add(masterPlanComponent);
masterPlan.Objectives = masterPlan.Objectives.Concat(masterPlanComponent.Objectives).ToList();
//masterPlanComponent.Objectives targets, I can see that both of them have 4 net targets as it should be
await _context.SaveChangesAsync();
_logger.LogInformation("New master plan component created.");
_logger.LogInformation("Master plan component id: " + masterPlanComponent.ComponentId.ToString());
//after I try to save the context however, only one of them has it.
return masterPlanComponent;
}
this code results in only 4 targets being written in the database each of them pointing to only one (the last one) of the objectives
This sounds like it is caused because you are creating the targets ahead of time, and then passing them to each objective. When you pass the targets you created to the first objective, EF starts tracking them and marks them as to-be-inserted. When you pass the same csharp objects by ref to the 2nd objective, they are already marked as to-be-inserted and are simply updated to be referencing the 2nd objective rather than the first.
Try creating new target objects in csharp for each objective. EF will only insert 1 row : 1 csharp object reference.