Ошибка первичного ключа .NET Core EF в context.SaveChanges () - PullRequest
0 голосов
/ 23 марта 2019

Моя 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 Ответ

1 голос
/ 25 марта 2019

Обычно это приводит к нескольким экземплярам IEntityChangeTracker (см .: Почему на мою сущность ссылаются несколько экземпляров IEntityChangeTracker? ), однако я подозреваю, что в вашем identityContext отключены прокси-серверы для отложенной загрузки, поэтому вы 'Вы получите исключение PK.

Проблема будет в том, что вы загружаете пользователя из одного контекста (identityContext) и пытаетесь сохранить ссылку на него через другой контекст.(контекст) Вы хотите загрузить ссылку из того же контекста.Контекст приложения знает о AppUser, но он не загружал экземпляр, который вы связываете с проектом, потому что он был загружен из другого контекста, поэтому он обрабатывает его как новый AppUser.

Решение состоит в том, чтобы загрузитьAppUser из context вместо identityContext

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();
    }
}

Если у вас нет DbSet для AspNetUser в контексте приложения, вам необходимо добавить его.Обычно для чего-то подобного я бы не добавил всю сущность AspNetUser в контекст приложения, а скорее облегченную сущность, содержащую только те детали, которые мне нужны (например, ID и имя), и тогда мои сущности приложения ссылались бы на этот облегченный экземпляр (указалв той же таблице) для ускорения операций с данными для этой ассоциации.

...