仅对登录用户更新-实体对象不能被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属性,即使是作为一个隐藏字段,我也有点不安。
我想这里有两个问题…
- 为什么我得到多实例错误,我如何解决它?
- 使用什么正确的方法/模式来确保当前登录的用户只能更新自己的UserProfile?
您的即时错误来自由上下文的两个实例跟踪的实体。也就是说,UserManager
是用应用程序上下文的实例实例化的,然后很可能你在控制器的某个地方定义了另一个实例。
您从UserManager
上下文中获取用户,将其分配给UserProfile
实例,然后尝试将UserProfile
实例保存到单独的上下文中。这包括保存中的用户,所以现在它在两个上下文中被跟踪。要解决这个问题,只需要确保只处理一个上下文实例。依赖注入通常是处理这个问题的最好方法。
但是,您可以通过简单地不使用UserProfile
来完全回避这个问题。Identity的全部意义在于为您提供可扩展的身份验证类,您可以扩展。UserProfile
对于simplemember是必要的,因为基本用户对象,即ASP。. NET会员用户,是否可以扩展。如果你只是添加你的配置文件属性到你的ApplicationUser
类,因为他们应该是,那么你甚至不需要工作任何其他的