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?
CodePudding user response:
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.