如何使用MVC5和实体框架,自定义属性更新IdentityUser [英] How to update IdentityUser with custom properties using MVC5 and entity framework

查看:2102
本文介绍了如何使用MVC5和实体框架,自定义属性更新IdentityUser的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是内置的用户身份管理框架,并想了几个自定义添加到AspNetUsers表。到目前为止,解决我遇到的每个问题会导致另一个问题。

I am using the built in identity framework for user management, and would like to add a few customizations to the AspNetUsers table. So far the solution to each problem I've encountered causes another problem.

如果我更改了用户模型(比如,通过增加一个zip code属性,并在AspNetUsers表中的匹配字段),然后调用UserManager.UpdateAsync(用户),它成功,但不更新的zip在数据库code字段。

If I make a change to the user model (say, by adding a zip code property and matching field in the AspNetUsers table), then call UserManager.UpdateAsync(user), it succeeds but does not update the zip code field in the database.

至少另外一个SO质疑曾试图解决这个。但建议的修复有打破其他事情:

At least one other SO question has tried to deal with this. But the suggested fixes there break other things:

1)创建UserDbContext的另一个实例,并试图连接用户对象会导致实体框架抱怨

1) Creating another instance of the UserDbContext and trying to attach the user object causes entity framework to complain that "An entity object cannot be referenced by multiple instances of IEntityChangeTracker"

2)关闭代理创建摆脱在#1中列出的问题,但导致的DbContext不加载子对象(如AspNetUserLogins,这是相当重要的)。

2) Turning off proxy creation gets rid of the problem listed in #1, but causes the dbcontext to not load child objects (like AspNetUserLogins, which are rather important).

另一解决方案是访问控制器创建的上下文。考虑默认的AccountController与使用MVC(第5版)一个新的ASP .NET Web应用程序构造方法的模板:

Another solution would be to access the context created in the Controller. Consider the default AccountController's constructor methods with a new ASP .NET Web Application using the MVC (version 5) template:

 public AccountController()
            : this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
        {
        }

        public AccountController(UserManager<ApplicationUser> userManager)
        {
            UserManager = userManager;
        }

应用程序上下文DB被创建,但也没有办法通过的UserManager访问它(因为'商店'的UserManager的私有财产)。

The application DB Context is created, but there is no way to access it via the UserManager (because the 'Store' private property of UserManager).

这似乎并不像火箭科学,所以我的猜测是,我做的事情围绕处理基本上是没错的/理解的DbContext生命周期。

This doesn't seem like rocket science, so my guess is that I am doing something basically wrong around handling/understanding the dbcontext lifecycle.

所以:我怎么正确地访问/使用的DbContext保存和更新AspNetUsers,相关的定制属性和preserve子对象(如AspNetUserLogins)?

So: how do I correctly access/use the dbcontext to save and update AspNetUsers, associated custom properties, and preserve child objects (like AspNetUserLogins)?

修改-------

还有一件事我想...

One more thing I tried...

我从默认更新的AccountController的构造:

I updated the AccountController's constructor from the default:

    public AccountController(UserManager<ApplicationUser> userManager)
    {
       UserManager = userManager;
    }

这样:

    public AccountController(UserManager<ApplicationUser> userManager)
    {
        userDbContext= new UserDbContext();
        UserStore<ApplicationUser> store = new UserStore<ApplicationUser>();
        UserManager<ApplicationUser> manager = new UserManager<ApplicationUser>(store);

        manager.UserValidator = new CustomUserValidator<ApplicationUser>(UserManager);

       // UserManager = userManager;
        UserManager = manager;

    }

在试图挂到的DbContext。后来,在一个公共异步任务法的身体,我尝试拨打:

In an attempt to hang on to the dbcontext. Later, in the body of a public async Task method, I attempt to call:

  var updated = await UserManager.UpdateAsync(user);

  if (updated.Succeeded)
  {
    userDbContext.Entry(user).State = System.Data.Entity.EntityState.Modified;
    await userDbContext.SaveChangesAsync();
  }

不过,状态更新的尝试将引发异常:

However, the attempt to update the state throws an exception:

已经有对于对象层类型'xyz.Models.ApplicationUser'生成的代理类型。当相同对象层类型由一个AppDomain两个或更多个不同的模型映射会出现这种情况。

"There is already a generated proxy type for the object layer type 'xyz.Models.ApplicationUser'. This occurs when the same object layer type is mapped by two or more different models in an AppDomain."

这看起来不正确......这是在构造函数中分配了相同的DbContext。

That doesn't seem right... it's the same dbcontext assigned in the constructor.

编辑#2 -----

下面是ApplicationUser模型:

Here is the ApplicationUser model:

using Microsoft.AspNet.Identity.EntityFramework;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using System.Data.Entity;

namespace xyz.App.Models
{
    // You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
    public class ApplicationUser : IdentityUser
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string ZipCode { get; set; }
        public string PasswordResetToken { get; set; }
        public System.DateTime? PasswordResetTokenExpiry { get; set; }

        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
        {
            // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            // Add custom user claims here
            return userIdentity;
        }

        public ApplicationUser() { }

    }




    public class UserDbContext : IdentityDbContext<ApplicationUser>
    {
        public UserDbContext()
            : base("DefaultConnection")
        {

        }

    }
}

最后编辑----------------------------

好吧,以后在评论一些来回,我意识到我是问在错误的道路的问题。我的问题是真的:如何使用code-第一,而不是数据库先迁移。从Hibernate放学回家,我已经习惯在Java中手动映射通过XML对象表或注释。

Ok, after some back and forth in the comments, I realized I was asking the question in the wrong way. My question was really: How to use Code-first rather than Database-first migrations. Coming from the Hibernate school, I had been used to manually mapping objects to tables via XML or annotations in Java.

所以,在飞掠<一个href=\"http://www.asp.net/mvc/tutorials/mvc-5/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and-openid-sign-on\">this文章,我错过了周围迁移的重要步骤。教训。

So, in skimming this article, I missed the important steps around migration. Lesson learned.

推荐答案

所以,你正在使用的数据库,而不是先code-第一。我第一次建议code,因为它的超级真棒。我,和你一样,开始了第一次使用的数据库,来代替。如果你不使用code为先,然后删除迁移表在数据库中。否则,就会造成问题。

So, you are using database-first instead of code-first. I recommend code first since it's super awesome. I, like you, started out using database first, instead. If you aren't using code-first, then delete the migrations table in your database. Otherwise, it will cause problems.

如果可能的话,我建议以下这code-第一个教程,极大地帮助了我。您可以轻松地添加自定义字段,以您的身份,并与远框架的完全集成身份验证进入。

If possible, I recommend following this code-first tutorial, which has helped me greatly. You can easily add custom fields to your identity and have full integration with the framework as far as authentication goes.

<一个href=\"http://blogs.msdn.com/b/webdev/archive/2013/10/16/customizing-profile-information-in-asp-net-identity-in-vs-2013-templates.aspx\">http://blogs.msdn.com/b/webdev/archive/2013/10/16/customizing-profile-information-in-asp-net-identity-in-vs-2013-templates.aspx

这篇关于如何使用MVC5和实体框架,自定义属性更新IdentityUser的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆