I am using Entity Framework 6 Code First. I have two Entities:
public class User
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public string Mail { get; set; }
public DateTime PwLastSet { get; set; }
public virtual ICollection<Group> Groups { get; set; }
}
and
public class Group
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public string Description{ get; set; }
public int GroupType { get; set; }
public virtual ICollection<User> Members { get; set; }
}
in a many-to-many relationship and a joining entity GroupUsers
which is generated automatically by EFCore and only includes the two Key properties from the original entities which make the primary key as well as foreign keys from the two base Entities. All this is fine and the database objects including the joining table have been created in the migration with no issues.
The problem starts when trying to Insert data into either of the two tables using EFCore.
private async Task SynchronizeUsersAsync()
{
var localUsers = await _userRepo.ListAllAsync();
List<User> remoteUsers = _usersHelper.GetUsers();
var toAdd = new List<User>();
foreach (var remoteUser in remoteUsers)
{
var localUser = localUsers.FirstOrDefault(x => x.Id.Equals(remoteUser.Id));
if (localUser == null)
{
toAdd.Add(remoteUser);
}
else if (!localUser.Equals(remoteUser))
{
_mapper.Map(remoteUser, localUser);
}
}
await DbContext.Set<User>().AddRangeAsync(toAdd);
await DbContext.SaveChangesAsync();
//delete is irrelevant at the moment
}
I get an exception:
System.InvalidOperationException: The instance of entity type 'Group' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.
As every User
potentially belongs to multiple Groups
this is also supposed to insert a new row into the joining table GroupUsers
for every object in ICollection<Group> Groups
of a User.
I have also tried replacing .AddRangeAsync()
with .AddAsync()
to Insert on every new User which ended up with the same exception.