Changing 'user' data from another controller

时间:2017-11-28 21:28:16

标签: c# asp.net-mvc entity-framework

I have been trying to update a user record from within the roles controller and keep hitting numerous errors. The latest error is the following exception:

System.InvalidOperationException: 'Attaching an entity of type 'TRIZTools.Models.User' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.'

Here's a copy of the code:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult RoleAddToUser(string UserId, string RoleName)
    {
        User user = context.Users.Where(u => u.Id.Equals(UserId, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
        var userManager = new UserManager<User>(new UserStore<User>(new ApplicationDbContext()));
        ViewBag.RolesForThisUser = userManager.GetRoles(user.Id);
        var idResult = userManager.AddToRole(user.Id, RoleName);
        if (user.AccountNew)
        {
            user.AccountNew = false;
            userManager.Update(user);
        }

It is failing at userManager.Update(user). I have tried the UpdateAsync, but that's failing too. Ideally what I want to do is set the user's new status to false, as this would make it easier to identify all the accounts that have been updated.

I am using Identity in my MVC framework and this method is not located in the AccountController.

Solution

With the assistance from @Rainman here is the the solution:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult RoleAddToUser(string UserId, string RoleName)
    {
        User user = context.Users.Where(u => u.Id.Equals(UserId, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
        var userManager = new UserManager<User>(new UserStore<User>(new ApplicationDbContext()));
        ViewBag.RolesForThisUser = userManager.GetRoles(user.Id);
        var idResult = userManager.AddToRole(user.Id, RoleName);
        if (user.AccountNew)
        {
            user.AccountNew = false;
            context.SaveChanges(); //This fixed it!
        }

2 个答案:

答案 0 :(得分:1)

我没有看到userManager.AddToRole方法,但我怀疑你可能更新了方法中的另一个用户实体。因此,用户实体标记为EntityState.Modified,并且您尝试在尚未更新之前更新另一个用户实体。因此,我们应该保存第一个实体,EF会将实体标记为EntityState.Unchanged,这样问题就可能解决了。要添加context.SaveChanges();,我修改了这样的方法;

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult RoleAddToUser(string UserId, string RoleName)
    {
        User user = context.Users.Where(u => u.Id.Equals(UserId, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
        var userManager = new UserManager<User>(new UserStore<User>(new ApplicationDbContext()));
        ViewBag.RolesForThisUser = userManager.GetRoles(user.Id);
        var idResult = userManager.AddToRole(user.Id, RoleName);
        context.SaveChanges(); // Add this line
        if (user.AccountNew)
        {
            user.AccountNew = false;
            userManager.Update(user);
        }
     }

答案 1 :(得分:1)

解决方案

在@Rainman的帮助下,这是解决方案:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult RoleAddToUser(string UserId, string RoleName)
    {
        User user = context.Users.Where(u => u.Id.Equals(UserId, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
        var userManager = new UserManager<User>(new UserStore<User>(new ApplicationDbContext()));
        ViewBag.RolesForThisUser = userManager.GetRoles(user.Id);
        var idResult = userManager.AddToRole(user.Id, RoleName);
        if (user.AccountNew)
        {
            user.AccountNew = false;
            context.SaveChanges(); //This fixed it!
        }