如何为Identity Framework设置实体框架模型以对抗现有数据库?

Luk*_*uke 9 c# entity-framework asp.net-identity

我正在将我的旧网站从PHP迁移到C#MVC.我想使用微软的Identity设置,因为它看起来很整洁.

我已经使用数据库优先实体框架设置了我的解决方案.我有所需的表(Users,UserRoles,UserLogins,UserClaims)和所有外键设置.

我已经看了几种方法来设置IdentityUser已经使用过MySqlDatabase和代码优先的方法,但是当我已经有一个已建立的数据库(包括现有的Users表)时,我不确定如何实现我的IdentityUser .

我希望我使用我已经创建的Entity Framework类IdentityUser来操纵我Users.有没有办法让我的User模型在EF中派生IdentityUser并匹配我现有的数据库?

我正在努力的一件事是我的数据库不使用string值作为主键,它使用自动递增int.

目前我有以下课程:

// Copyright (c) KriaSoft, LLC.  All rights reserved.  See LICENSE.txt in the project root for license information.

namespace KriaSoft.AspNet.Identity.EntityFramework
{
    using Microsoft.AspNet.Identity;
    using System;

    public partial class IdentityUser : IUser<int>
    {
        /// <summary>
        /// Default constructor 
        /// </summary>
        public IdentityUser()
        {
            Id = Guid.NewGuid().ToString();
        }

        /// <summary>
        /// Constructor that takes user name as argument
        /// </summary>
        /// <param name="userName"></param>
        public IdentityUser(string userName)
            : this()
        {
            UserName = userName;
        }

        /// <summary>
        /// User ID
        /// </summary>
        public string Id { get; set; }

        /// <summary>
        /// User's name
        /// </summary>
        public string UserName { get; set; }

        /// <summary>
        ///     Email
        /// </summary>
        public virtual string Email { get; set; }

        /// <summary>
        ///     True if the email is confirmed, default is false
        /// </summary>
        public virtual bool EmailConfirmed { get; set; }

        /// <summary>
        ///     The salted/hashed form of the user password
        /// </summary>
        public virtual string PasswordHash { get; set; }

        /// <summary>
        ///     A random value that should change whenever a users credentials have changed (password changed, login removed)
        /// </summary>
        public virtual string SecurityStamp { get; set; }

        /// <summary>
        ///     PhoneNumber for the user
        /// </summary>
        public virtual string PhoneNumber { get; set; }

        /// <summary>
        ///     True if the phone number is confirmed, default is false
        /// </summary>
        public virtual bool PhoneNumberConfirmed { get; set; }

        /// <summary>
        ///     Is two factor enabled for the user
        /// </summary>
        public virtual bool TwoFactorEnabled { get; set; }

        /// <summary>
        ///     DateTime in UTC when lockout ends, any time in the past is considered not locked out.
        /// </summary>
        public virtual DateTime? LockoutEndDateUtc { get; set; }

        /// <summary>
        ///     Is lockout enabled for this user
        /// </summary>
        public virtual bool LockoutEnabled { get; set; }

        /// <summary>
        ///     Used to record failures for the purposes of lockout
        /// </summary>
        public virtual int AccessFailedCount { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,我的Users实体框架数据库上下文中的实体已经具有所有这些属性,所以在那里以及我的上下文中指定它们似乎有点无意义......我真的不确定:(.

我想我的问题是:如何使用我现有的实体框架User模型(数据库优先)作为我的Asp.net Identity的IdentityUser?

Luk*_*uke 9

我现在对此更熟悉了.

使代码优先或数据库优先的最简单方法是更改​​现有数据库,使其至少具有ASP.NET身份使用的最小数据库模式(表,列和外键)框架.

您可以在下图中看到最小架构:

最小身份框架模式

虽然它没有列类型,但仍然有用.您可以从此页面上列出SQL数据库项目模板中获取精确的模式.

我确信通过在代码(代码优先)中创建某种映射或使用EF工具(数据库优先)从列名映射到映射,可以避免必须使现有数据库遵循此模式.代码中的另一个名字......但我还没试过.

我从头创建了大部分表,除了User表,我将原始Username列更改为名称UserName(大小写更正)以匹配并添加了尚未存在的其他列.

代码优先

一旦您拥有数据库并且您知道模式是正确的,那么您可能需要考虑使用reverse-engineer code firstVisual Studio 的功能来为您构建EF类.这样,您的新EF类将精确匹配您的表格布局.否则,您必须自己使用所有映射对所有模型进行编码.

一旦准备好EF类,就应该让它们从Identity Framework中的不同类继承.当您首先作为代码执行此操作时,您可以将继承添加到EF类,而不必担心它们被覆盖(与数据库优先不同).

public class User : IdentityUser<int, UserLogin, UserRole, UserClaim>
{
    // Any additional columns from your existing users table will appear here.
}

public class Role : IdentityRole<int, UserRole>
{
}

public class UserClaim : IdentityUserClaim<int>
{
}

public class UserLogin : IdentityUserLogin<int>
{
}

public class UserRole : IdentityUserRole<int>
{
}
Run Code Online (Sandbox Code Playgroud)

请注意int每个中指定的内容,它指定User表的主键类型.默认情况下,这是一个字符串,但Id我现有数据库中的值是int自动递增的值.

数据库优先

当您首先使用EF数据库时,您无法直接将Identity Framework类的继承添加到自动生成的类中.这是因为每次使用Entity Framework Visual Studio工具更改模型时都会覆盖它们.

但是,创建的类是自动生成的所有partial类,因此可以通过创建一个新文件来实现,该文件具有不会被覆盖的部分类的定义.它们必须位于相同的名称空间中且名称完全相同.

例如,这可能是EF生成的类:

namespace Dal
{
    public partial class User
    {
        // This class is auto generated by using EF database-first
        // We can't edit this class to add the inheritance,
        // because it will be overwritten every time
        // we update our model using the database-first tools
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我们可以创建的模型,用于将我们的继承添加到:

// same namespace as existing class
namespace Dal
{
    // Same name as existing class
    public partial class User : IdentityUser<int, UserLogin, UserRole, UserClaim>
    {
        // This can probably be left blank
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,您将为ASP.NET Identity Framework所需的每个类执行此操作:

public partial class User : IdentityUser<int, UserLogin, UserRole, UserClaim>
{
    // Any additional columns from your existing users table will appear here.
}

public partial class Role : IdentityRole<int, UserRole>
{
}

public partial class UserClaim : IdentityUserClaim<int>
{
}

public partial class UserLogin : IdentityUserLogin<int>
{
}

public partial class UserRole : IdentityUserRole<int>
{
}
Run Code Online (Sandbox Code Playgroud)