1

I have following sample JSON (simplified):

{
   "programmes":[
      {
             "programmeID":"163",
             "title":"Programme 1",
             "color":"#ff5f57",
             "moderators":[
                {
                   "moderatorID":"27",
                   "name":"Moderator 1",
                }
             ]
          },
          {
             "programmeID":"153",
             "title":"Programme 2",
             "color":"#ff5f57",
             "moderators":[
                {
                   "moderatorID":"27",
                   "name":"Moderator 1",
                }
             ]
          },

       ]
}

I want to convert into following objects:

    public class Programme
    {
        [Key]
        public string programmeID { get; set; }
        public string title { get; set; }

        //Navigational Property
        public virtual ICollection<Moderator> moderators { get; set; }
    }

    public class Moderator
    {
        [Key]
        public string moderatorID { get; set; }
        public string name { get; set; }

        //Navigational Property
        public virtual ICollection<Programme> programmes { get; set; }
    }

Everything is fine, objects looks great, populated correctly, but when trying to save into db a get this error:

The instance of entity type 'Moderator' cannot be tracked because another instance with the key value '{moderatorID: 27}' is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.

This error happens when calling .Add with the list of Programmes:

List<Programme> programmes;
programmes = JsonSerializer.Deserialize<List<Programme>>(JSONcontent);
//... db init
db.AddRange(programmes);

I understand that there is a duplicity for Moderator (ID=27), but I think that it's quite a normal pattern in JSON. I can do some workaround, but wondering if there is any best practice how to handle this in EF directly?

  • You have to show the code are you trying to add to db – Serge May 09 '22 at 14:26
  • From what you wrote, the save appears to be trying to do an insert and not an update. – ΩmegaMan May 09 '22 at 14:27
  • this might help: https://stackoverflow.com/questions/62278581/saving-deserialized-json-objects-to-database-with-duplicate-child-entities – nilsK May 09 '22 at 14:31
  • simplified code added, good point that it's not update, but insert. The problem is how to handle correctly. – Tomas Svestka May 09 '22 at 14:46
  • Do you want insert only programme or the 2 entity? See this link https://stackoverflow.com/questions/25441027/how-do-i-stop-entity-framework-from-trying-to-save-insert-child-objects – Den May 09 '22 at 14:56

1 Answers1

0

you can not add children you are created from deserialization as an existed ones. One of the solutions is finding the existed children at first

List<Programme> programmes = JsonSerializer.Deserialize<List<Programme>>(JSONcontent);

foreach (var program in programmes)
{
var moderators=new List<Moderator>();
foreach (var moderator in program.moderators)
{
     var existingModerator=db.Moderators.FirstOrDefault(i=> 
                 i.moderatorId=moderator.moderatorId);
    moderators.Add(existingModerator);
}
  programm.moderators=moderators;
}
db.AddRange(programmes);

but I usually prefer to create an explicit class for many to many relations. It will make all your code much more simple.

Serge
  • 40,935
  • 4
  • 18
  • 45