我正在向DbContext添加一个带有从客户端传递的导航属性的新实体,但不是EF识别导航属性实体已经存在,而是尝试重新插入它,因为你不能有重复的主键。
var profile = _mapper.Map<Profile>(profileDto);
profile.User.LockoutEnabled = true;
profile.User.Password = new PasswordHasher<User>().HashPassword(profile.User, "*********");
profile.Company = null; // Doing this works fine but otherwise it fails.
await _dataContext.Set<Profile>().AddAsync(profile);
await _dataContext.SaveChangesAsync();
profile.Company = await _dataContext.Set<Company>().FindAsync(profile.CompanyId);
return _mapper.Map<ProfileCreateDto>(profile);
由于取消Company实体或更改客户端以仅传递CompanyId而不是Company值可以正常工作,我仍然想理解为什么EF试图重新插入现有实体。
EF正在尝试重新插入Company
实体,因为您正在使用AddAsync
方法插入Profile
实体。
AddAsync
方法导致存在问题的实体(Profile
)及其在实体图中的所有相关实体(例如Company
)被标记为Added
。标记为Added
的实体意味着-This is a new entity and it will get inserted on the next SaveChanges call.
参见详细信息-DbSet<TEntity>.AddAsync()
。
作为一般解决方案,在断开连接的场景中,当使用实体图创建新实体(具有一个或多个相关实体)时,使用Attach
方法代替。
Attach
方法使任何实体只有在没有设置主键值时才被标记为Added
。否则,该实体被标记为Unchanged
。标记为Unchanged
的实体意味着-This entity already exists in the database and it might get updated on the next SaveChanges call.
参见详细信息-DbSet<TEntity>.Attach()
我希望这能满足你的好奇心。