将默认IdentityDbContext替换为现有数据库信息

时间:2014-08-04 17:46:07

标签: c# asp.net asp.net-identity

我需要将ASP.NET Web API添加到已有活动用户数据库的系统中。

根据我使用asp.net内置的默认Identity的经验,它通常使用代码优先方法从头开始创建表。这显然不是我想要的方法。

我如何将Identity Model指向我当前的数据库,而不是创建一个新数据库?

我似乎无法找到一个体面的教程或如何在线?

我假设我必须在身份包中的某些位置实现一个接口,以便我提供正常操作所需的最小字段。

我想为用户角色和用户身份执行此操作。

我首先将当前数据库导入代码吗?

{编辑}

这是我的表格的链接: ERD

3 个答案:

答案 0 :(得分:4)

可以通过覆盖OnModelCreating事件来映射ASP.NET Identity对象和属性。这看起来像 -

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    var user = modelBuilder.Entity<IdentityUser>().HasKey(u => u.Id).ToTable("User", "Users"); //Specify our our own table names instead of the defaults

    user.Property(iu => iu.Id).HasColumnName("Id");
    user.Property(iu => iu.UserName).HasColumnName("UserName");
    user.Property(iu => iu.Email).HasColumnName("EmailAddress").HasMaxLength(254).IsRequired();
    user.Property(iu => iu.IsConfirmed).HasColumnName("EmailConfirmed");
    user.Property(iu => iu.PasswordHash).HasColumnName("PasswordHash");
    user.Property(iu => iu.SecurityStamp).HasColumnName("SecurityStamp");

    user.HasMany(u => u.Roles).WithRequired().HasForeignKey(ur => ur.UserId);
    user.HasMany(u => u.Claims).WithRequired().HasForeignKey(uc => uc.UserId);
    user.HasMany(u => u.Logins).WithRequired().HasForeignKey(ul => ul.UserId);
    user.Property(u => u.UserName).IsRequired();
...

对每个实体使用“ToTable”,为每个属性使用“HasColumnName”,您应该能够映射到自己的模式。

显而易见的问题是,这只会允许您更改列名和表名,而不是列类型。

您可以扩展IdentityUser类以添加与架构中其他数据库列匹配的新属性,并且可以更改用户和角色的主键类型(请参阅http://aspnet.codeplex.com/SourceControl/latest#Samples/Identity/ChangePK/readme.txt),但核心列类型和信息需要相同。这很可能是密码哈希列的问题,在ASP.NET身份的情况下,它实际上包含哈希和盐。

如果您有现有的用户凭据,则可能需要对其进行翻译 - 从http://www.asp.net/identity/overview/migrations/migrating-an-existing-website-from-sql-membership-to-aspnet-identity并使用https://aspnet.codeplex.com/SourceControl/latest#Samples/Identity/SQLMembership-Identity-OWIN/Migrations.sql处的脚本

提供了从SQL成员身份执行此操作的过程。

该过程的关键点是 -

  

加密并存储应用程序用户的密码   在数据库中。 SQL成员资格中使用的加密算法是   与新身份系统中的不同。重用旧的   我们需要在旧用户登录时有选择地解密密码的密码   在使用加密时使用SQL成员资格算法   新用户身份识别算法。

可能也可以在使用以前的成员资格算法成功登录后暂时保留密码,然后使用明文字符串将密码添加到使用ASP的新ASP.NET身份密码列.NET Identity散列和用户管理器机制 - 但在这种情况下,您应该非常小心地传递纯文本凭据。在成功迁移之后,如果将来发生破坏,您还应该销毁先前系统中的(更弱的哈希)凭证(如果在迁移到明显更强大的哈希ASP.NET Identity列之后未更改凭证)。 p>

答案 1 :(得分:3)

就此而言,

IdentityDbContext与正常DbContext没有什么不同。如果您不希望它创建表,那么您只需将其视为数据库优先(是的,您可能会混淆地拥有数据库优先的代码优先项目)。

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("ConnectionStringName")
    {
        Database.SetInitializer<ApplicationDbContext>(null);
    }
}

当然,您必须将此上下文与您进行迁移的应用程序上下文分开,但现在它将不再尝试创建数据库或生成表。

答案 2 :(得分:0)

另一个选项可能是子类Microsoft.AspNet.Identity.EntityFramework.IdentityDbContext<Models.ApplicationUser>,这显然只适用于你还没有继承另一个DbContext派生类型的时候。

例如:

public class MyDbContext : IdentityDbContext<ApplicationUser>, IMyDbContext
{
    public IDbSet<MyOtherEntity> OtherEntities { get; set; }
    public MyDbContext() : base("MyDb", false)
    {
        Database.SetInitializer<MyDbContext>(null);
    }
    public static DbContext Create()
    {
        return new MyDbContext();
    }
}

您需要修改 Startup.Auth.cs 并更新app.CreatePerOwinContext调用,而不是参考新DbContext类型的Create()方法(或任何DI-您已经在已建立的成熟产品中使用的基于分配器。)请记住,您在此处提供的方法返回的类型是用于未来Owin上下文Get()调用的类型。

因此,您还需要编辑 IdentityConfig.cs ,而不是引用MyDbContext类型(而不是ApplicationDbContext)。否则此方法将失败。如果在编辑后,您在此处获得空引用异常,则表示您未正确编辑 Startup.Auth.cs (请参阅上一段。)

您也可以明确评论出位于 IdentityModels.cs 中的默认支架ApplicationDbContext,以便其他开发人员在将来不会感到困惑,它也应该有助于您识别任何挥之不去的引用(不应该有任何。)

对于大多数常见情况,上述内容应该足够了,如果您现有的数据库架构与默认生成的架构不同,您可以覆盖{@ 1}},如@pwdst接受的答案中所述(除了详情如上。)