0

I have this method:

public async Task<TrainingPlan> CreateTrainingPlan(TrainingPlanDTO trainingPlan)
{
   TrainingPlan tp = new TrainingPlan
   {
     Name = trainingPlan.Name
   };

   // adding to context
   _context.TrainingPlan.Add(tp);

   // assign database identity id to property 
   trainingPlan.ResourceId = tp.Id;

   // more entities being saved in dbcontext

   // final save in database
   await dbcontext.SaveChangesAsync();
}

What I would want is to assign the identity id of the entity inserted after the insert in the database itself was done in order to not do multiple calls to the database. I have tested the method and trainingPlan.ResourceId is always 0 as it takes the initial value of tp.Id, not the new one that is assigned after the SaveChangesAsync method has been called.

I would need to hold a reference to the tp.Id. Is it possible to user ref keyword in this case?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Daniel
  • 261
  • 3
  • 18
  • 1
    EF doesn't talk to the database until `SaveChangesAsync` is called so there will be no `tp.id` until then. So in your given example you'd just move the `trainingPlan.ResourceId = tp.Id;` to after that but what are you trying to stop having multiple database calls? As in your example there isn't multiple, only one :) – Matt Jan 09 '22 at 12:11
  • 2
    Agree with Matt. You could perhaps hook up property changed notifications so that when EF edits the Id of the entity you saved, an event goes out to any registered interestees – Caius Jard Jan 09 '22 at 12:22
  • Yes, the Id is created only after SaveChangesAsync is done, but I want to keep a reference to that field so when the id is being assigned to the efcore entity to also be asigned to the Resourceid property. There are a lot more entities to be saved in the database but I wanted to keep the example short. – Daniel Jan 09 '22 at 12:23
  • @CaiusJard I will try that and see if it works. – Daniel Jan 09 '22 at 12:24
  • Incidentally you don't need to add an entity, save, get the id, put the id in a related entity, save... you just build your full load of related objects and save the parent one. If you want to make life easy in terms of going the other way too, look at a mapper library- it would reduce your code to more like 4 lines: map from dto, add, save, map back to dto - it's the mapper's job to make a new ent from the dto, and to copy the Id back and probably less effort than setting up a prop change notifier system – Caius Jard Jan 09 '22 at 17:04
  • @CaiusJard I have a lot of nested entites stored in lists which are added in the context using a foreach. How would autommaper know which entity id from the database to be mapped to the correct dto entity ? – Daniel Jan 09 '22 at 19:34
  • Well, it wouldn't really matter? The DTOs come in they're transformed to ents, saved and the ents are transformed back to DTOs; whether they're the exact same DTO at memory location X with an updated Id of 1 and a name of Bob.. or whether it's a brand new DTO at memory location Y with a new Id of 1 and a name of Bob.. the front end won't know or care the difference between X and Y – Caius Jard Jan 09 '22 at 20:19

1 Answers1

0

Another option is to use a manually generated primary key - perhaps a guid, instead of using an automatically generated integer value. Then you can assign the new guid to whatever object(s) you are creating before saving the data to the database. You would also need to change the type of your primary key object and related object keys to match whatever primary key type you want to use.

private class TrainingPlan
{
public Guid ResourceID
public string Name
}

trainingPlan.ResourceID = Guid.NewGuid();
trainingPlan.subObject.parentTrainingPlan = trainingPlan.ResourceID
await dbcontext.SaveChangesAsync();
TroyB
  • 16
  • 1