I have an object Manager, which has property EmailAccount, type EmailAccount:
public class Manager
{
.....
public virtual EmailAccount EmailAccount { get; set; }
}
public partial class EmailAccount : BaseEntity
{
public int Id { get; set; }
public string Email { get; set; }
public string DisplayName { get; set; }
....
public virtual Manager Manager { get; set; }
}
and mapping between these classes:
public class ManagerMap : EntityTypeConfiguration<Manager>
{
public ManagerMap()
{
this.ToTable("Manager");
this.HasKey(dp => dp.Id);
this.Property(p => p.FirstName).IsRequired().HasMaxLength(250);
this.Property(p => p.LastName).IsRequired().HasMaxLength(250);
this.Property(p => p.Nickname).HasMaxLength(250);
this.HasOptional(c => c.EmailAccount)
.WithRequired(a => a.Manager)
.Map(m => m.MapKey("ManagerId"));
}
}
then in code I get object Manager from context and update it
var manager = _managerService.GetManager(user.Id);
manager.FirstName = model.FirstName;
manager.LastName = model.LastName;
manager.Nickname = model.Nickname;
manager.EmailAccount = mapper.Map<EmailAccount>(model.EmailAccount);
So, as we can see, EmailAccount is not gotten from context but uses an external object, but with Id (PK) the same as in context!
Then, before save changes, I try to attach this object to context:
_db.EmailAccounts.Attach(manager.EmailAccount);
but I got an error:
Saving or accepting changes failed because more than one entity of type 'Infrastructure.Asset.Messages.EmailAccount' have the same primary key value. Ensure that explicitly set primary key values are unique.
ADDED
_managerService.GetManager(user.Id)
calls the following method:
public Manager GetManager(string aspNetUserId)
{
var manager = _db.Managers
.Include(p => p.EmailAccount)
.Where(p => p.AspNetUser.Id == aspNetUserId)
.FirstOrDefault();
return manager;
}
Why so, and how do I do it?
There is no need to attach it in your case. The following line is sufficient:
manager.EmailAccount = mapper.Map<EmailAccount>(model.EmailAccount);
Although, you are correct by stating that EmailAccount
isn't bound to the context, the manager
object is. By assigning the email account, it will be tracked.
If you do need to attach an object to the context, or want to implement some up-sert logic, see this MSDN page.