繁体   English   中英

在 .Net 核心和 .Net 标准身份框架之间共享通用数据库

[英]Sharing common database between .Net core and .Net standard Identity framework

我有使用Identity 2.0的旧版 MVC 应用程序。 最近,我还使用Identity 6.0 (AspNetCore.Identity.EntityFrameworkCore) 创建了 .Net 6 API。

注意:在这两个框架中都有一些与架构相关的变化,比如一些额外的表和字段。 检查我最后添加的快照。

问题是我必须管理的公共数据库。

  • 我已经尝试并成功完成了使用最新模式更新现有数据库。
  • 我还迁移了身份表的数据。
  • 我现在面临的唯一问题是我不确定如何进一步支持旧的遗留应用程序。 (我想拥有旧的应用程序,但希望它使用新的身份表。)
  • 由于现有/旧应用程序位于 .Net 框架 4.6.1 中,因此我无法真正更新身份,并且它的表中包含最新模式。 (我不介意做任何黑客或任何修复。旧应用程序应该与最新的身份模式一起工作,这对我来说是重要的。)

有没有什么选项可以在不更改代码的情况下遵循,我的截止日期很紧,我真的不想创建外部 API 来验证旧的遗留应用程序 任何帮助或想法将不胜感激。

在此处输入图像描述

我没有找到任何方法来更新现有应用程序(.Net 标准 4.6)以支持新的身份结构。 所以这就是我为解决这个问题所做的。

  1. 正如#Jeremy在评论中所建议的那样,我将我的 .Net 核心身份模型配置为具有不同的名称(默认情况下其他名称,因此它与现有表没有任何冲突) https://docs.microsoft.com/en-us/ aspnet/core/security/authentication/customize-identity-model?view=aspnetcore-6.0#change-tablecolumn-names-and-facets (保持模型配置的顺序与线程中给出的一样。我保留我的base.OnModelCreating(builder);在构建器配置下方。)
  2. 我找到了一个脚本来创建身份表架构和移动记录。 见下面的截图。 _New表示 .Net 核心标识表 scehma。 我已在此处附加该脚本,并且已在公共数据库中运行此脚本。

在此处输入图像描述

  1. 所以现在我有一个包含新旧身份表的通用数据库。 旧应用程序仍然指向旧表并与旧表一起工作,而 .Net 核心身份框架指向新数据库。
  2. 由于我已将所有数据和记录从旧表移动到新表,因此我也可以在新的身份应用程序中访问它们。
  3. 到目前为止,我不需要在新应用程序中运行迁移,所以我禁用了它。 但有人担心如果我运行迁移会如何影响现有数据库。 所以我做了一些研发,发现我们可以创建迁移,在运行迁移之前,我们可以在 up 和 down 方法中注释掉代码。 之后,我们可以运行此迁移并更新数据库。 基本上是空迁移以与现有数据库保持同步。 (尚未检查此工作,但如果我需要,这是我的想法)

这是我使用的 sql 脚本。

第 1 步:更改现有表的名称

EXEC sp_rename 'AspNetRoles', 'AspNetRoles_old';
EXEC sp_rename 'AspNetUserClaims', 'AspNetUserClaims_old';
EXEC sp_rename 'AspNetUserLogins', 'AspNetUserLogins_old';
EXEC sp_rename 'AspNetUserRoles', 'AspNetUserRoles_old';
EXEC sp_rename 'AspNetUsers', 'AspNetUsers_old';

第 2 步:创建 ASP.NET Core 身份表

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
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 (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO


SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AspNetRoles](
[Id] [nvarchar](450) NOT NULL,
[Name] [nvarchar](256) NULL,
[NormalizedName] [nvarchar](256) NULL,
[ConcurrencyStamp] [nvarchar](max) NULL,
 CONSTRAINT [PK_AspNetRoles] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO


SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AspNetUserClaims](
[Id] [int] IDENTITY(1,1) NOT NULL,
[UserId] [nvarchar](450) NOT NULL,
[ClaimType] [nvarchar](max) NULL,
[ClaimValue] [nvarchar](max) NULL,
 CONSTRAINT [PK_AspNetUserClaims] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO


SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AspNetUserLogins](
[LoginProvider] [nvarchar](128) NOT NULL,
[ProviderKey] [nvarchar](128) NOT NULL,
[ProviderDisplayName] [nvarchar](max) NULL,
[UserId] [nvarchar](450) NOT NULL,
 CONSTRAINT [PK_AspNetUserLogins] PRIMARY KEY CLUSTERED
(
[LoginProvider] ASC,
[ProviderKey] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO


SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AspNetUserRoles](
[UserId] [nvarchar](450) NOT NULL,
[RoleId] [nvarchar](450) NOT NULL,
 CONSTRAINT [PK_AspNetUserRoles] PRIMARY KEY CLUSTERED
(
[UserId] ASC,
[RoleId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO


SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AspNetUsers](
[Id] [nvarchar](450) NOT NULL,
[UserName] [nvarchar](256) NULL,
[NormalizedUserName] [nvarchar](256) NULL,
[Email] [nvarchar](256) NULL,
[NormalizedEmail] [nvarchar](256) NULL,
[EmailConfirmed] [bit] NOT NULL,
[PasswordHash] [nvarchar](max) NULL,
[SecurityStamp] [nvarchar](max) NULL,
[ConcurrencyStamp] [nvarchar](max) NULL,
[PhoneNumber] [nvarchar](max) NULL,
[PhoneNumberConfirmed] [bit] NOT NULL,
[TwoFactorEnabled] [bit] NOT NULL,
[LockoutEnd] [datetimeoffset](7) NULL,
[LockoutEnabled] [bit] NOT NULL,
[AccessFailedCount] [int] NOT NULL,
 CONSTRAINT [PK_AspNetUsers] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO


SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AspNetUserTokens](
[UserId] [nvarchar](450) NOT NULL,
[LoginProvider] [nvarchar](128) NOT NULL,
[Name] [nvarchar](128) NOT NULL,
[Value] [nvarchar](max) NULL,
 CONSTRAINT [PK_AspNetUserTokens] PRIMARY KEY CLUSTERED
(
[UserId] ASC,
[LoginProvider] ASC,
[Name] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO


CREATE NONCLUSTERED INDEX [IX_AspNetRoleClaims_RoleId] ON [dbo].[AspNetRoleClaims]
(
[RoleId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO


CREATE UNIQUE NONCLUSTERED INDEX [RoleNameIndex] ON [dbo].[AspNetRoles]
(
[NormalizedName] ASC
)
WHERE ([NormalizedName] IS NOT NULL)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO


CREATE NONCLUSTERED INDEX [IX_AspNetUserClaims_UserId] ON [dbo].[AspNetUserClaims]
(
[UserId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO


CREATE NONCLUSTERED INDEX [IX_AspNetUserLogins_UserId] ON [dbo].[AspNetUserLogins]
(
[UserId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO


CREATE NONCLUSTERED INDEX [IX_AspNetUserRoles_RoleId] ON [dbo].[AspNetUserRoles]
(
[RoleId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO


CREATE NONCLUSTERED INDEX [EmailIndex] ON [dbo].[AspNetUsers]
(
[NormalizedEmail] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO


CREATE UNIQUE NONCLUSTERED INDEX [UserNameIndex] ON [dbo].[AspNetUsers]
(
[NormalizedUserName] ASC
)
WHERE ([NormalizedUserName] IS NOT NULL)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
ALTER TABLE [dbo].[AspNetRoleClaims]  WITH CHECK ADD  CONSTRAINT [FK_AspNetRoleClaims_AspNetRoles_RoleId] FOREIGN KEY([RoleId])
REFERENCES [dbo].[AspNetRoles] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[AspNetRoleClaims] CHECK CONSTRAINT [FK_AspNetRoleClaims_AspNetRoles_RoleId]
GO
ALTER TABLE [dbo].[AspNetUserClaims]  WITH CHECK ADD  CONSTRAINT [FK_AspNetUserClaims_AspNetUsers_UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[AspNetUsers] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[AspNetUserClaims] CHECK CONSTRAINT [FK_AspNetUserClaims_AspNetUsers_UserId]
GO
ALTER TABLE [dbo].[AspNetUserLogins]  WITH CHECK ADD  CONSTRAINT [FK_AspNetUserLogins_AspNetUsers_UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[AspNetUsers] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[AspNetUserLogins] CHECK CONSTRAINT [FK_AspNetUserLogins_AspNetUsers_UserId]
GO
ALTER TABLE [dbo].[AspNetUserRoles]  WITH CHECK ADD  CONSTRAINT [FK_AspNetUserRoles_AspNetRoles_RoleId] FOREIGN KEY([RoleId])
REFERENCES [dbo].[AspNetRoles] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[AspNetUserRoles] CHECK CONSTRAINT [FK_AspNetUserRoles_AspNetRoles_RoleId]
GO
ALTER TABLE [dbo].[AspNetUserRoles]  WITH CHECK ADD  CONSTRAINT [FK_AspNetUserRoles_AspNetUsers_UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[AspNetUsers] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[AspNetUserRoles] CHECK CONSTRAINT [FK_AspNetUserRoles_AspNetUsers_UserId]
GO
ALTER TABLE [dbo].[AspNetUserTokens]  WITH CHECK ADD  CONSTRAINT [FK_AspNetUserTokens_AspNetUsers_UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[AspNetUsers] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[AspNetUserTokens] CHECK CONSTRAINT [FK_AspNetUserTokens_AspNetUsers_UserId]
GO

第 3 步:将数据从旧表 (ASP.NET Identity) 迁移到新表 (ASP.NET Core Identity)

INSERT INTO AspNetRoles ([Id], [Name], [NormalizedName], [ConcurrencyStamp])
SELECT [Id], [Name], UPPER([Name]), LOWER(NEWID()) FROM Objectra_Development.dbo.AspNetRoles

INSERT INTO AspNetUsers ([Id], [UserName], [NormalizedUserName], [Email], [NormalizedEmail], [EmailConfirmed], [PasswordHash], [SecurityStamp], [ConcurrencyStamp], [PhoneNumber], [PhoneNumberConfirmed], [TwoFactorEnabled], [LockoutEnd], [LockoutEnabled], [AccessFailedCount], 
AssignObjects, AccessOwnObjectsOnly, UserObjectId, UserObjectDefd, GoogleAuth, LastPasswordResetDate, FriendlyName, AccessibleObjectDefinitions)
SELECT [Id], [UserName], UPPER([UserName]), [Email], UPPER([Email]), [EmailConfirmed], [PasswordHash], [SecurityStamp], LOWER(NEWID()), [PhoneNumber], [PhoneNumberConfirmed], 0, null, 1, 0, 
AssignObjects, AccessOwnObjectsOnly, UserObjectId, UserObjectDefd, GoogleAuth, LastPasswordResetDate, FriendlyName, AccessibleObjectDefinitions
FROM Objectra_Development.dbo.AspNetUsers;

INSERT INTO AspNetUserRoles ([UserId], [RoleId])
SELECT [UserId], [RoleId] 
FROM Objectra_Development.dbo.AspNetUserRoles;

我遇到了同样的问题,最终使用模式创建了新的身份核心表。

builder.ToTable(name: "Users", "Identity");
builder.ToTable(name: "Roles", "Identity");
builder.ToTable(name: "UserRoles", "Identity");
builder.ToTable(name: "UserClaims", "Identity");
builder.ToTable(name: "UserLogins", "Identity");
builder.ToTable(name: "UserTokens", "Identity");
builder.ToTable(name: "RoleClaims", "Identity");

然后我在旧的身份用户表上使用了一个触发器来保持新的身份用户表同步。

CREATE/*ALTER*/ TRIGGER [dbo].[IdentityUsers_Sync] ON [dbo].[Users] 
AFTER INSERT, UPDATE AS 
BEGIN
    --INSERT
    IF NOT EXISTS (SELECT * FROM deleted)
        BEGIN
            INSERT INTO [Identity].[Users] 
            (
                Id,
                UserName,
                NormalizedUserName,
                Email,
                NormalizedEmail,
                EmailConfirmed,
                PasswordHash,
                SecurityStamp,
                PhoneNumber,
                PhoneNumberConfirmed,
                TwoFactorEnabled,
                LockoutEnabled,
                AccessFailedCount
            )
            SELECT
                Id,
                UserName,
                UPPER(UserName),
                Email,
                UPPER(Email),
                EmailConfirmed,
                PasswordHash,
                SecurityStamp,
                PhoneNumber,
                PhoneNumberConfirmed,
                TwoFactorEnabled,
                0,
                0
            FROM inserted
        END
    --UPDATE
    IF EXISTS (SELECT * FROM inserted) AND EXISTS (SELECT * FROM deleted)
        BEGIN
            UPDATE iu
            SET 
                iu.UserName = i.UserName,
                iu.NormalizedUserName = UPPER(i.UserName),
                iu.Email = i.Email,
                iu.NormalizedEmail = UPPER(i.Email),
                iu.EmailConfirmed = i.EmailConfirmed,
                iu.PasswordHash = i.PasswordHash,
                iu.SecurityStamp = i.SecurityStamp,
                iu.PhoneNumber = i.PhoneNumber,
                iu.PhoneNumberConfirmed = i.PhoneNumberConfirmed,
                iu.TwoFactorEnabled = i.TwoFactorEnabled,
                iu.LockoutEnabled = 0,
                iu.AccessFailedCount = 0
            FROM [Identity].[Users] iu, inserted i
            WHERE iu.Id = i.Id
        END
END
GO
ALTER TABLE [dbo].[Users] ENABLE TRIGGER [IdentityUsers_Sync]
GO

我的计划是在遗留系统中创建一个 api 控制器来处理新注册(通过任何新核心应用程序中的 HttpClient)。 然后触发器将拾取它并保持新系统同步。

让遗留系统使用新的身份表在这一点上看起来不是一个选项。 也许可以将其他字段添加到新架构中并使用触发器来填充它们? 没试过。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM