Обновление только для зарегистрированных пользователей. На объектный объект нельзя ссылаться несколькими экземплярами IEntityChangeTracker.

Прежде всего, пожалуйста, потерпите меня, так как я довольно новичок в MVC/Entity Framework. Я пытаюсь сделать частичное обновление базы данных кода структуры сущности сначала для конкретного авторизованного пользователя, используя MVC5...

Я создал дополнительный класс UserProfile для расширения класса asp.net Identity ApplicationUser. Вот код:

public class UserProfile
{
    [Key, ForeignKey("ApplicationUser")]
    public string UserId { get; set; }

    public virtual ApplicationUser ApplicationUser { get; set; }

    public string Username { get; set; }
}

Я также расширил класс ApplicationUser, включив в него класс UserProfile в качестве дополнительного свойства:

public class ApplicationUser : IdentityUser
{
    public virtual UserProfile UserProfile { get; set; }
}

Затем я расширил класс AccountController (автоматически генерируется с использованием asp.net Identity), чтобы добавить дополнительный метод с именем Welcome...

[HttpPost]
[ValidateAntiForgeryToken]
[Authorize]
public ActionResult Welcome([Bind(Include = "UserId,Username")] UserProfile userProfile)
{
    var user = UserManager.FindById(User.Identity.GetUserId());

    if (ModelState.IsValid)
    {
        userProfile.ApplicationUser = user;

        db.UserProfile.Attach(userProfile);
        db.Entry(userProfile).Property(u => u.Username).IsModified = true;
        db.SaveChanges();

        return RedirectToAction("Index", "Home");
    }

    return View(userProfile);
}

Однако, когда я пытаюсь отправить форму и выполнить метод Welcome, я получаю следующую ошибку:

На объектный объект нельзя ссылаться несколькими экземплярами IEntityChangeTracker.

Я пробовал обычный поиск в Google, чтобы понять, как / почему это происходит, но не понимаю, как я могу иметь несколько экземпляров IEntityChangeTracker?

Для дальнейшего пояснения я пытаюсь убедиться, что только текущий зарегистрированный пользователь может обновить объект UserProfile (по какой-то причине я не могу найти хороший шаблон для этого?).

Я также знаю, что, поскольку FK UserId доступен в модели UserProfile, я мог бы просто пропустить установку userProfile.ApplicationUser и написать условие, подобное этому:

if (userProfile.UserId == user.Id)

Однако, насколько я понимаю, читая статьи и учебные пособия по EF, в этом случае это не должно быть необходимым? Мне также немного неудобно показывать свойство UserId на странице, даже в виде скрытого поля.

Итак, я полагаю, что здесь есть два вопроса...

  1. Почему я получаю ошибку нескольких экземпляров и как ее устранить?
  2. Какой правильный метод / шаблон следует использовать, чтобы гарантировать, что пользователь, вошедший в систему в данный момент, может обновить только свой собственный UserProfile?

1 ответ

Ваша непосредственная ошибка связана с тем, что сущность отслеживается двумя экземплярами вашего контекста. А именно, UserManager создается с экземпляром контекста вашего приложения, а затем, скорее всего, вы определяете другой экземпляр где-то в вашем контроллере.

Вы получаете пользователя из UserManager контекст, назначьте его UserProfile экземпляр, а затем попытайтесь сохранить UserProfile экземпляр в отдельный контекст. Это включает в себя пользователя в сохранении, так что теперь он отслеживается в двух контекстах. Чтобы это исправить, вам просто нужно убедиться, что вы имеете дело только с одним экземпляром контекста. Внедрение зависимости обычно является лучшим способом справиться с этим.

Тем не менее, вы можете полностью обойти проблему, просто не имея UserProfile, Весь смысл идентичности состоит в том, чтобы предоставить вам расширяемые классы аутентификации, которые вы можете расширить. UserProfile было необходимо с SimpleMembership, потому что базовый пользовательский объект, член ASP.NET, не мог быть расширен. Если вы просто добавите свойства своего профиля на свой ApplicationUser класс, как они должны быть, то вам не нужно даже работать что-нибудь еще.

Другие вопросы по тегам