仅对登录用户更新-实体对象不能被IEntityChangeTracker的多个实例引用

本文关键字:IEntityChangeTracker 引用 实例 不能 对象 登录 用户 更新 实体 | 更新日期: 2023-09-27 18:17:14

首先,请原谅我,因为我对MVC/实体框架相当陌生。我正在尝试使用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实例引用。

我已经尝试了通常的谷歌搜索,以了解如何/为什么这是发生的,但不明白我怎么能有任何IEntityChangeTracker的多个实例?

为了进一步澄清,我在这里试图做的是确保只有当前登录的用户才能更新UserProfile对象(由于某种原因,我在任何地方都找不到一个好的模式?)。

我还意识到,由于FK UserId在UserProfile模型上是可用的,所以我可以简单地忽略设置UserProfile。并编写如下条件:

if (userProfile.UserId == user.Id)

然而,从我对阅读EF的文章和教程的理解来看,这在这种情况下应该没有必要?对于在页面上公开UserId属性,即使是作为一个隐藏字段,我也有点不安。

我想这里有两个问题…

  1. 为什么我得到多实例错误,我如何解决它?
  2. 使用什么正确的方法/模式来确保当前登录的用户只能更新自己的UserProfile?

仅对登录用户更新-实体对象不能被IEntityChangeTracker的多个实例引用

您的即时错误来自由上下文的两个实例跟踪的实体。也就是说,UserManager是用应用程序上下文的实例实例化的,然后很可能你在控制器的某个地方定义了另一个实例。

您从UserManager上下文中获取用户,将其分配给UserProfile实例,然后尝试将UserProfile实例保存到单独的上下文中。这包括保存中的用户,所以现在它在两个上下文中被跟踪。要解决这个问题,只需要确保只处理一个上下文实例。依赖注入通常是处理这个问题的最好方法。

但是,您可以通过简单地不使用UserProfile来完全回避这个问题。Identity的全部意义在于为您提供可扩展的身份验证类,您可以扩展UserProfile对于simplemember是必要的,因为基本用户对象,即ASP。. NET会员用户,是否可以扩展。如果你只是添加你的配置文件属性到你的ApplicationUser类,因为他们应该是,那么你甚至不需要工作任何其他的

相关文章:
  • 没有找到相关文章