上下文上的.NET Core EF主键错误.SaveChanges()

时间:2019-03-23 16:39:41

标签: entity-framework asp.net-core asp.net-identity

我的Project模型具有<AppUsers>的集合:

public class Project
    {
        public int ProjectID { get; set; }

        [Required(ErrorMessage = " Please enter a project name")]
        public string Name { get; set; }

        [Required(ErrorMessage = " Please enter a project description")]
        public string Description { get; set; }

        public virtual ICollection<AppUser> ProjectManagers { get; set; }
}

public class AppUser : IdentityUser
    {
       //just a placeholder for now until I add properties later
    }

在我的EF信息库中,尝试将任何用户分配给多个项目作为ProjectManager集合的一部分时出现错误(例如,我可以将他们分配给Project1,但是当我将他们分配给Project2会引发异常)。

public void AddProjectManager(int projectID, AppUser user)
        {
            Project proj = context.Projects.Include(p => p.ProjectManagers).FirstOrDefault(p => p.ProjectID == projectID);
            if (!proj.ProjectManagers.Any(pm => pm.Id == user.Id))
            {
                AppUser appUser = identityContext.AspNetUsers.FirstOrDefault(p => p.Id == user.Id);
                if (appUser != null)
                {
                    proj.ProjectManagers.Add(appUser);
                    //ERROR OCCURS HERE WHEN I TRY TO SAVE
                    context.SaveChanges();
                }
            }
        }

我收到以下错误:

Violation of PRIMARY KEY constraint 'PK_AppUser'. Cannot insert duplicate key in object 'dbo.AppUser'. The duplicate key value is (xxx).

我尝试使用UserManager方法,但遇到相同的错误

1 个答案:

答案 0 :(得分:1)

通常这会导致多个IEntityChangeTracker实例(请参阅:Why is my entity being referenced by multiple instances of IEntityChangeTracker?),但是我怀疑您的identityContext已关闭了延迟加载代理,因此您将获得PK异常。

问题将是您正在从一个上下文(identityContext)加载用户,并试图通过另一个上下文保存对该用户的引用。 (上下文)您要从同一上下文加载引用。应用程序上下文了解AppUser,但是它没有加载您要与该项目关联的实例,因为该实例是从其他上下文加载的,因此将其视为新的AppUser。

解决方案是从context而不是identityContext加载AppUser

public void AddProjectManager(int projectID, AppUser user)
{
    Project proj = context.Projects.Include(p => p.ProjectManagers).FirstOrDefault(p => p.ProjectID == projectID);
    if (!proj.ProjectManagers.Any(pm => pm.Id == user.Id))
    {
         AppUser appUser = context.AspNetUsers.Single(p => p.Id == user.Id);
         proj.ProjectManagers.Add(appUser);
         context.SaveChanges();
    }
}

如果在应用程序上下文中没有AspNetUser的DbSet,则需要添加它。通常对于这样的事情,我不会将整个AspNetUser实体添加到应用程序上下文中,而是将一个仅包含我需要的详细信息(例如ID和Name)的轻量级实体添加,然后我的应用程序实体将引用该轻量级实例(指向在同一张表中)以加快与此关联的数据操作。