如何将身份用户从MVC5应用程序迁移到ASP.NET Core 2.2应用程序

时间:2018-12-21 01:07:01

标签: c# .net asp.net-mvc asp.net-core

我有一个使用Identity在MVC5上构建的Web应用程序。我想将此项目转换为ASP.NET Core 2.2 Web应用程序。我创建了一个新的ASP.NET Core 2.2 Web应用程序,其身份验证设置为“个人用户帐户”,并按照these instructions将数据库添加到项目中。然后,我在项目中添加了一个新的Identity Scaffolded项目,并添加了迁移并更新了数据库。

我注册了一个测试用户,当我检查SQL管理服务器时,我看到它为该项目创建了一个新数据库,即使我的连接字符串适用于旧数据库也是如此。

我想保留我的旧数据库,但是将其转换为使用ASP.NET Core内置的新Identity Razor页面。最好的方法是什么?

5 个答案:

答案 0 :(得分:4)

升级身份表后,您可能想要更新现有用户密码哈希。 AspNetUsers表中的某些新列将具有NULL值。首先运行:

UPDATE AspNetUsers SET NormalizedEmail = UPPER(Email), NormalizedUserName = UPPER(Email)
WHERE NormalizedEmail IS NULL
  

NormalizedUserName实际上是用大写的电子邮件更新的。

我们需要一种方法来区分哪些用户正在使用新的哈希版本。

一种方法是向IdentityUser添加新属性:

public class ApplicationUser : IdentityUser
{
    public PasswordHashVersion HashVersion { get; set; }

    public ApplicationUser()
    {
        this.HashVersion = PasswordHashVersion.Core;
    }
}

public enum PasswordHashVersion
{
    OldMvc,
    Core
}

现有用户的默认PasswordHashVersion等于零(OldMvc),新注册的用户默认值为1(Core)。如果您有一种更聪明的方法来检测哈希是来自新算法还是旧算法,则不需要。

然后,我们创建一个使用old default hash algorithm implementation的自定义PasswordHash:

public class OldMvcPasswordHasher : PasswordHasher<ApplicationUser>
{
    public override PasswordVerificationResult VerifyHashedPassword(ApplicationUser user, string hashedPassword, string providedPassword)
    {
        // if it's the new algorithm version, delegate the call to parent class
        if (user.HashVersion == PasswordHashVersion.Core)
            return base.VerifyHashedPassword(user, hashedPassword, providedPassword);

        byte[] buffer4;
        if (hashedPassword == null)
        {
            return PasswordVerificationResult.Failed;
        }
        if (providedPassword == null)
        {
            throw new ArgumentNullException("providedPassword");
        }
        byte[] src = Convert.FromBase64String(hashedPassword);
        if ((src.Length != 0x31) || (src[0] != 0))
        {
            return PasswordVerificationResult.Failed;
        }
        byte[] dst = new byte[0x10];
        Buffer.BlockCopy(src, 1, dst, 0, 0x10);
        byte[] buffer3 = new byte[0x20];
        Buffer.BlockCopy(src, 0x11, buffer3, 0, 0x20);
        using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(providedPassword, dst, 0x3e8))
        {
            buffer4 = bytes.GetBytes(0x20);
        }
        if (AreHashesEqual(buffer3, buffer4))
        {
            user.HashVersion = PasswordHashVersion.Core;
            return PasswordVerificationResult.SuccessRehashNeeded;
        }
        return PasswordVerificationResult.Failed;
    }

    private bool AreHashesEqual(byte[] firstHash, byte[] secondHash)
    {
        int _minHashLength = firstHash.Length <= secondHash.Length ? firstHash.Length : secondHash.Length;
        var xor = firstHash.Length ^ secondHash.Length;
        for (int i = 0; i < _minHashLength; i++)
            xor |= firstHash[i] ^ secondHash[i];
        return 0 == xor;
    }
}

此类继承了新的Identity Core PasswordHasher。如果用户的密码哈希版本已在使用新算法(例如HashVersion = Core),则我们只需从PasswordHasher调用使用新算法的基本方法即可。否则,请使用旧的身份算法来验证密码。

如果密码匹配,我们会将用户密码哈希版本更新为Core,然后返回PasswordVerificationResult.SuccessRehashNeeded,以使用新算法强制更新现有哈希。

最后,您需要确保使用了自定义PasswordHasher。将其添加到Startup.cs内的ConfigureServices

// Replace the existing scoped IPasswordHasher<> implementation
services.Replace(new ServiceDescriptor(
    serviceType: typeof(IPasswordHasher<ApplicationUser>),
    implementationType: typeof(OldMvcPasswordHasher),
    ServiceLifetime.Scoped));
  

必须在对AddIdentityAddDefaultIdentityAddIdentityCore进行任何调用之后将其添加。

这将在您的用户进行身份验证时缓慢更新密码哈希。

答案 1 :(得分:3)

我能够按照以下步骤将.NET 4.5.2项目成功迁移到.NET Core 3.1

  1. 使用Scaffold-DbContext基于现有数据库[1]
  2. 创建模型
Scaffold-DbContext [-Connection] [-Provider] [-OutputDir] [-Context] [-Schemas>] [-Tables>] [-DataAnnotations] [-Force] [-Project] [-StartupProject] [<CommonParameters>]
  1. 从生成的上下文以及不再需要的.cs文件中删除所有与AspNet相关的表。

  2. base.OnModelCreating(modelBuilder);添加到上下文文件中生成的OnModelCreating方法中。 [2]

  3. 运行以下脚本来更新/创建身份表[3] [4]

ALTER TABLE ASPNETROLES
ADD
 ConcurrencyStamp VARCHAR(255) NULL,               
 NormalizedName VARCHAR(255) NULL

 DROP TABLE AspNetUserTokens

 CREATE TABLE [AspNetUserTokens] (
    [UserId]        NVARCHAR (450) NOT NULL,
    [LoginProvider] NVARCHAR (450) NOT NULL,
    [Name]          NVARCHAR (450) NOT NULL,
    [Value]         NVARCHAR (MAX) NULL,
    CONSTRAINT [PK_AspNetUserTokens]
 PRIMARY KEY CLUSTERED ([UserId] ASC, [LoginProvider] ASC, [Name] ASC)
)

ALTER TABLE AspNetUsers
 ADD
 ConcurrencyStamp VARCHAR(255) NULL,
 LockoutEnd DATETIME NULL,
 NormalizedEmail VARCHAR(255) NULL,
 NormalizedUserName VARCHAR(255) NULL

DROP TABLE [AspNetRoleClaims]

CREATE TABLE [AspNetRoleClaims] (
    [Id]         INT            IDENTITY (1, 1) NOT NULL,
    [ClaimType]  NVARCHAR (MAX) NULL,
    [ClaimValue] NVARCHAR (MAX) NULL,
    [RoleId]     NVARCHAR (128) NOT NULL,
    CONSTRAINT [PK_AspNetRoleClaims]
 PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [FK_AspNetRoleClaims_AspNetRoles_RoleId]
 FOREIGN KEY ([RoleId])
  REFERENCES [dbo].[AspNetRoles] ([Id]) ON DELETE CASCADE
)


GO
CREATE NONCLUSTERED INDEX [IX_AspNetRoleClaims_RoleId]
    ON [AspNetRoleClaims]([RoleId] ASC)

ALTER TABLE AspNetUserLogins
   ADD ProviderDisplayName VARCHAR(255) NULL

UPDATE AspNetUsers SET NormalizedEmail = UPPER(Email), NormalizedUserName = UPPER(UserName)
WHERE NormalizedEmail IS NULL
  1. Startup.cs文件上,设置密码散列器兼容模式以考虑IdentityV2
services.Configure<PasswordHasherOptions>(options => options.CompatibilityMode = PasswordHasherCompatibilityMode.IdentityV2);

答案 2 :(得分:1)

我已经编写了用于迁移到 AspNetCore身份的SQL脚本。

此脚本与 AspNet Identity 完全向后兼容,因为我已向表中添加了新列并扩展了已经存在的列。

让我们看一下通过Scheme compare生成的屏幕截图:

AspNetUsers

AspNetRoles

AspNetUserLogins

下面您可以看到最终的脚本

BEGIN TRANSACTION;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET XACT_ABORT ON;

GO
PRINT N'Starting dropping constraints';

GO
ALTER TABLE [dbo].[AspNetUserRoles]
    DROP CONSTRAINT [FK_dbo.AspNetUserRoles_dbo.AspNetRoles_RoleId];

GO
ALTER TABLE [dbo].[AspNetUserRoles]
    DROP CONSTRAINT [FK_dbo.AspNetUserRoles_dbo.AspNetUsers_UserId];

GO
ALTER TABLE [dbo].[AspNetUserClaims]
    DROP CONSTRAINT [FK_dbo.AspNetUserClaims_dbo.AspNetUsers_UserId];

GO
ALTER TABLE [dbo].[AspNetUserLogins]
    DROP CONSTRAINT [FK_dbo.AspNetUserLogins_dbo.AspNetUsers_UserId];

-----------------------------------------------------------------------------
GO
PRINT N'Starting rebuilding table [dbo].[AspNetRoles]...';

GO
BEGIN TRANSACTION;
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    SET XACT_ABORT ON;

    CREATE TABLE [dbo].[tmp_ms_xx_AspNetRoles] (
        [Id]               NVARCHAR (450) NOT NULL,
        [Name]             NVARCHAR (256) NULL,
        [NormalizedName]   NVARCHAR (256) NULL,
        [ConcurrencyStamp] NVARCHAR (MAX) NULL,
        CONSTRAINT [tmp_ms_xx_constraint_PK_AspNetRoles1] PRIMARY KEY CLUSTERED ([Id] ASC) WITH (FILLFACTOR = 80)
    );

    IF EXISTS (SELECT TOP 1 1 
               FROM   [dbo].[AspNetRoles])
        BEGIN
            INSERT INTO [dbo].[tmp_ms_xx_AspNetRoles] ([Id], [Name], [NormalizedName], [ConcurrencyStamp])
            SELECT   [Id],
                     [Name],
                     UPPER([Name]),
                     NEWID()
            FROM     [dbo].[AspNetRoles]
            ORDER BY [Id] ASC;
        END

    DROP TABLE [dbo].[AspNetRoles];

    EXECUTE sp_rename N'[dbo].[tmp_ms_xx_AspNetRoles]', N'AspNetRoles';
    EXECUTE sp_rename N'[dbo].[tmp_ms_xx_constraint_PK_AspNetRoles1]', N'PK_AspNetRoles', N'OBJECT';

COMMIT TRANSACTION;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

GO
CREATE UNIQUE NONCLUSTERED INDEX [RoleNameIndex]
    ON [dbo].[AspNetRoles]([Name] ASC) WHERE ([Name] IS NOT NULL) WITH (FILLFACTOR = 80);

GO
CREATE UNIQUE NONCLUSTERED INDEX [RoleNormalizedNameIndex]
    ON [dbo].[AspNetRoles]([NormalizedName] ASC) WHERE ([NormalizedName] IS NOT NULL) WITH (FILLFACTOR = 80);

-------------------------------------------------------------------
GO
PRINT N'Starting rebuilding table [dbo].[AspNetUserClaims]...';

GO
BEGIN TRANSACTION;
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    SET XACT_ABORT ON;

    CREATE TABLE [dbo].[tmp_ms_xx_AspNetUserClaims] (
        [Id]         INT            IDENTITY (1, 1) NOT NULL,
        [UserId]     NVARCHAR (450) NOT NULL,
        [ClaimType]  NVARCHAR (MAX) NULL,
        [ClaimValue] NVARCHAR (MAX) NULL,
        CONSTRAINT [tmp_ms_xx_constraint_PK_AspNetUserClaims1] PRIMARY KEY CLUSTERED ([Id] ASC) WITH (FILLFACTOR = 80)
    );

    IF EXISTS (SELECT TOP 1 1 
               FROM   [dbo].[AspNetUserClaims])
        BEGIN
            SET IDENTITY_INSERT [dbo].[tmp_ms_xx_AspNetUserClaims] ON;
            INSERT INTO [dbo].[tmp_ms_xx_AspNetUserClaims] ([Id], [UserId], [ClaimType], [ClaimValue])
            SELECT   [Id],
                     [UserId],
                     [ClaimType],
                     [ClaimValue]
            FROM     [dbo].[AspNetUserClaims]
            ORDER BY [Id] ASC;
            SET IDENTITY_INSERT [dbo].[tmp_ms_xx_AspNetUserClaims] OFF;
        END

    DROP TABLE [dbo].[AspNetUserClaims];

    EXECUTE sp_rename N'[dbo].[tmp_ms_xx_AspNetUserClaims]', N'AspNetUserClaims';
    EXECUTE sp_rename N'[dbo].[tmp_ms_xx_constraint_PK_AspNetUserClaims1]', N'PK_AspNetUserClaims', N'OBJECT';

COMMIT TRANSACTION;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

GO
CREATE NONCLUSTERED INDEX [IX_AspNetUserClaims_UserId]
    ON [dbo].[AspNetUserClaims]([UserId] ASC) WITH (FILLFACTOR = 80);

-------------------------------------------------------------------
GO
PRINT N'Starting rebuilding table [dbo].[AspNetUserLogins]...';

GO
BEGIN TRANSACTION;
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    SET XACT_ABORT ON;

    CREATE TABLE [dbo].[tmp_ms_xx_AspNetUserLogins] (
        [LoginProvider]       NVARCHAR (450) NOT NULL,
        [ProviderKey]         NVARCHAR (450) NOT NULL,
        [ProviderDisplayName] NVARCHAR (MAX) NULL,
        [UserId]              NVARCHAR (450) NOT NULL,
        CONSTRAINT [tmp_ms_xx_constraint_PK_AspNetUserLogins1] PRIMARY KEY CLUSTERED ([LoginProvider] ASC, [ProviderKey] ASC, [UserId] ASC) WITH (FILLFACTOR = 80)
    );

    IF EXISTS (SELECT TOP 1 1 
               FROM   [dbo].[AspNetUserLogins])
        BEGIN
            INSERT INTO [dbo].[tmp_ms_xx_AspNetUserLogins] ([LoginProvider], [ProviderKey], [UserId])
            SELECT   [LoginProvider],
                     [ProviderKey],
                     [UserId]
            FROM     [dbo].[AspNetUserLogins]
            ORDER BY [LoginProvider] ASC, [ProviderKey] ASC;
        END

    DROP TABLE [dbo].[AspNetUserLogins];

    EXECUTE sp_rename N'[dbo].[tmp_ms_xx_AspNetUserLogins]', N'AspNetUserLogins';
    EXECUTE sp_rename N'[dbo].[tmp_ms_xx_constraint_PK_AspNetUserLogins1]', N'PK_AspNetUserLogins', N'OBJECT';
COMMIT TRANSACTION;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;


GO
CREATE NONCLUSTERED INDEX [IX_AspNetUserLogins_UserId]
    ON [dbo].[AspNetUserLogins]([UserId] ASC) WITH (FILLFACTOR = 80);

-------------------------------------------------------------------
GO
PRINT N'Starting rebuilding table [dbo].[AspNetUserRoles]...';

GO
BEGIN TRANSACTION;
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    SET XACT_ABORT ON;

    CREATE TABLE [dbo].[tmp_ms_xx_AspNetUserRoles] (
        [UserId] NVARCHAR (450) NOT NULL,
        [RoleId] NVARCHAR (450) NOT NULL,
        CONSTRAINT [tmp_ms_xx_constraint_PK_AspNetUserRoles1] PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC) WITH (FILLFACTOR = 80)
    );

    IF EXISTS (SELECT TOP 1 1 
               FROM   [dbo].[AspNetUserRoles])
        BEGIN
            INSERT INTO [dbo].[tmp_ms_xx_AspNetUserRoles] ([UserId], [RoleId])
            SELECT   [UserId],
                     [RoleId]
            FROM     [dbo].[AspNetUserRoles]
            ORDER BY [UserId] ASC, [RoleId] ASC;
        END

    DROP TABLE [dbo].[AspNetUserRoles];

    EXECUTE sp_rename N'[dbo].[tmp_ms_xx_AspNetUserRoles]', N'AspNetUserRoles';
    EXECUTE sp_rename N'[dbo].[tmp_ms_xx_constraint_PK_AspNetUserRoles1]', N'PK_AspNetUserRoles', N'OBJECT';

COMMIT TRANSACTION;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

GO
CREATE NONCLUSTERED INDEX [IX_AspNetUserRoles_RoleId]
    ON [dbo].[AspNetUserRoles]([RoleId] ASC) WITH (FILLFACTOR = 80);
-------------------------------------------------------------------
GO
PRINT N'Starting rebuilding table [dbo].[AspNetUsers]...';

GO
BEGIN TRANSACTION;
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    SET XACT_ABORT ON;

    CREATE TABLE [dbo].[tmp_ms_xx_AspNetUsers] (
        [Id]                   NVARCHAR (450)     NOT NULL,
        [Email]                NVARCHAR (256)     NULL,
        [NormalizedEmail]      NVARCHAR (256)     NULL,
        [EmailConfirmed]       BIT                NOT NULL,
        [PasswordHash]         NVARCHAR (MAX)     NULL,
        [SecurityStamp]        NVARCHAR (MAX)     NULL,
        [PhoneNumber]          NVARCHAR (MAX)     NULL,
        [PhoneNumberConfirmed] BIT                NOT NULL,
        [TwoFactorEnabled]     BIT                NOT NULL,
        [LockoutEndDateUtc]    DATETIME           NULL,
        [LockoutEnd]           DATETIMEOFFSET (7) NULL,
        [LockoutEnabled]       BIT                NOT NULL,
        [AccessFailedCount]    INT                NOT NULL,
        [UserName]             NVARCHAR (256)     NULL,
        [NormalizedUserName]   NVARCHAR (256)     NULL,
        [ConcurrencyStamp]     NVARCHAR (MAX)     NULL,
        CONSTRAINT [tmp_ms_xx_constraint_PK_AspNetUsers1] PRIMARY KEY CLUSTERED ([Id] ASC) WITH (FILLFACTOR = 80)
    );

    IF EXISTS (SELECT TOP 1 1 
               FROM   [dbo].[AspNetUsers])
        BEGIN
            INSERT INTO [dbo].[tmp_ms_xx_AspNetUsers] (
                     [Id], 
                     [Email],
                     [NormalizedEmail],
                     [EmailConfirmed],
                     [PasswordHash],
                     [SecurityStamp],
                     [PhoneNumber],
                     [PhoneNumberConfirmed],
                     [TwoFactorEnabled],
                     [LockoutEnabled],
                     [AccessFailedCount],
                     [UserName],
                     [NormalizedUserName],
                     [ConcurrencyStamp])
            SELECT   [Id],
                     [Email],
                     UPPER([Email]),
                     [EmailConfirmed],
                     [PasswordHash],
                     [SecurityStamp],
                     [PhoneNumber],
                     [PhoneNumberConfirmed],
                     [TwoFactorEnabled],
                     [LockoutEnabled],
                     [AccessFailedCount],
                     [UserName],
                     UPPER([UserName]),
                     NEWID()
            FROM     [dbo].[AspNetUsers]
            ORDER BY [Id] ASC;
        END

    DROP TABLE [dbo].[AspNetUsers];

    EXECUTE sp_rename N'[dbo].[tmp_ms_xx_AspNetUsers]', N'AspNetUsers';
    EXECUTE sp_rename N'[dbo].[tmp_ms_xx_constraint_PK_AspNetUsers1]', N'PK_AspNetUsers', N'OBJECT';

COMMIT TRANSACTION;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

GO
CREATE UNIQUE NONCLUSTERED INDEX [UserNameIndex]
    ON [dbo].[AspNetUsers]([UserName] ASC) WHERE ([UserName] IS NOT NULL) WITH (FILLFACTOR = 80);

GO
CREATE UNIQUE NONCLUSTERED INDEX [NormalizedUserNameIndex]
    ON [dbo].[AspNetUsers]([NormalizedUserName] ASC) WHERE ([NormalizedUserName] IS NOT NULL) WITH (FILLFACTOR = 80);

GO
CREATE NONCLUSTERED INDEX [EmailIndex]
    ON [dbo].[AspNetUsers]([NormalizedEmail] ASC) WITH (FILLFACTOR = 80);

-------------------------------------------------------------------
GO
CREATE TABLE [dbo].[AspNetRoleClaims] (
    [Id]         INT            IDENTITY (1, 1) NOT NULL,
    [RoleId]     NVARCHAR (450) NOT NULL,
    [ClaimType]  NVARCHAR (MAX) NULL,
    [ClaimValue] NVARCHAR (MAX) NULL,
    CONSTRAINT [PK_AspNetRoleClaims] PRIMARY KEY CLUSTERED ([Id] ASC) WITH (FILLFACTOR = 80)
);

GO
CREATE NONCLUSTERED INDEX [IX_AspNetRoleClaims_RoleId]
    ON [dbo].[AspNetRoleClaims]([RoleId] ASC) WITH (FILLFACTOR = 80);

-------------------------------------------------------------------
GO
PRINT N'Creating [dbo].[AspNetUserTokens]...';

GO
CREATE TABLE [dbo].[AspNetUserTokens] (
    [UserId]        NVARCHAR (450) NOT NULL,
    [LoginProvider] NVARCHAR (450) NOT NULL,
    [Name]          NVARCHAR (450) NOT NULL,
    [Value]         NVARCHAR (MAX) NULL,
    CONSTRAINT [PK_AspNetUserTokens] PRIMARY KEY CLUSTERED ([UserId] ASC, [LoginProvider] ASC, [Name] ASC) WITH (FILLFACTOR = 80)
);

-------------------------------------------------------------------
GO
PRINT N'Creating [dbo].[__EFMigrationsHistory]...';


GO
CREATE TABLE [dbo].[__EFMigrationsHistory] (
    [MigrationId]    NVARCHAR (150) NOT NULL,
    [ProductVersion] NVARCHAR (32)  NOT NULL,
    CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY CLUSTERED ([MigrationId] ASC) WITH (FILLFACTOR = 80)
);

--GO
--INSERT INTO [dbo].[__EFMigrationsHistory]
--           ([MigrationId], [ProductVersion])
--VALUES
--            ('20200406184458_InitialCreate',    '2.2.6-servicing-10079')
-------------------------------------------------------------------
GO
PRINT N'Creating constraints';

GO
ALTER TABLE [dbo].[AspNetUserLogins] WITH NOCHECK
    ADD CONSTRAINT [FK_AspNetUserLogins_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE;

GO
ALTER TABLE [dbo].[AspNetUserRoles] WITH NOCHECK
    ADD CONSTRAINT [FK_AspNetUserRoles_AspNetRoles_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[AspNetRoles] ([Id]) ON DELETE CASCADE;

GO
ALTER TABLE [dbo].[AspNetUserRoles] WITH NOCHECK
    ADD CONSTRAINT [FK_AspNetUserRoles_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE;

GO
ALTER TABLE [dbo].[AspNetUserClaims] WITH NOCHECK
    ADD CONSTRAINT [FK_AspNetUserClaims_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE;

GO
ALTER TABLE [dbo].[AspNetRoleClaims] WITH NOCHECK
    ADD CONSTRAINT [FK_AspNetRoleClaims_AspNetRoles_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[AspNetRoles] ([Id]) ON DELETE CASCADE;

GO
ALTER TABLE [dbo].[AspNetUserTokens] WITH NOCHECK
    ADD CONSTRAINT [FK_AspNetUserTokens_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE;
-------------------------------------------------------------------

GO
PRINT N'Update complete.';

COMMIT TRANSACTION;

答案 3 :(得分:0)

尽管Microsoft documentation有所帮助。最有用的信息是在评论中。

我能够使用以下步骤迁移现有数据库:

  • 创建一个新的ASP.net Core项目并将其ModelSnapshot修改为
    与EF6匹配。之后,您可以为chnages生成脚本 EF6到EF Core。

  • 编写脚本以更新AspNetUsers表。在ASP.net核心中
    身份验证时使用的身份NormalizedEmail,
    NormalizedUserName列。所以我们需要更新这两列
    使用我们现有的数据。

这是脚本的GitHub链接,用于更新表。 Migration.zip

答案 4 :(得分:0)

另一种解决方案是将数据导出/导入到新表中。这是出于几个不同的原因而做的,但是最终不想更改我的原始源表,以防万一我需要快速轻松地返回它。

长话短说,您可以将旧数据直接导入/导出到新的Identity表中,唯一需要做的就是标准化的用户名和电子邮件值。

如果Identity能够在内部处理(更新)新密码哈希,安全性戳记和并发性戳记,而在用户首次登录时没有问题,则可以在内部进行处理,那就太好了。

我使用完整的密码迁移用户的超级快捷方式:

1)将旧版本的Identity上的users表导出到CSV文件。

2)在Excel中打开该csv文件,并在CSV文件中为三个缺少的规范化列(用户名和电子邮件)和一个缺少的并发戳记列(未真正需要并发列)添加三列)。

3)在第一个空白标准化列(通常为c2)中,添加Excel公式=UPPER(b2)(其中b2是您要标准化的第一个值的字段...例如,在直接导出中将Username = b2或Email = d2放在其中,将标准化列放在非标准化列旁边。按Enter键,您现在应该在字段中看到大写字母值。

4)将该公式向下拖动到电子表格的末尾,以将所有用户名和电子邮件标准化为它们的大写值(即所有大写=标准化)。

5)将大写值从电子表格中复制并粘贴到一个空的记事本文件中...然后将它们复制回电子表格中的同一位置(这将用规范化的公式覆盖公式Excel可能足够聪明,可以摆脱公式并将标准化的值保存在CSV保存中,但我没有对其进行测试。

6)将电子表格另存为CSV并将其导入到新的身份AspnetUsers表中。

并发标记可以保留为空白,并且当用户首次登录时,最新的身份将负责其他所有事情。

如果您尚未在新版本中启用用户名,也不会在旧版本中启用用户名,那么该身份也不会登录(因此您需要先启用该功能或​​将用户名转换为相关的电子邮件地址,然后才能成功登录) )。

这不是一件很漂亮的事情,但是对于一次工作,我用不到15分钟的时间便用这种方法将用户从Identity 4.0.30319迁移到Core 2.2,并且不需要更改密码。我输入所有这些内容所花的时间比迁移用户所需的时间长。希望对您有所帮助。