迁移现有用户数据到ABP vNext

用户,ABP vNext,数据 · 浏览次数 : 130

小编点评

**ABP 数据库迁移指南** **简介** 当您使用 ABP 进行项目拆分时,可能需要对老数据进行迁移。由于 ABP 中的用户管理系统基于 ASP.NET Identity,老用户表可能包含与多租户管理相关的字段,导致平滑迁移难以进行。 **迁移步骤** 1. **导出数据库表** - 创建一个 SQL 文件,包含要迁移的数据库表。 - 使用 SQL 客户端或工具导出数据。 2. **修改数据库表定义** - 在 `IdentityUser` 和 `IdentityRole` 表中添加 `Email` 字段,使其为必填。 - 确保 `Email` 字段在旧系统中存在。 3. **修改 IdentityUserStore** - 在 `SetEmailAsync` 方法中,设置 `Email` 字段的默认值。 - 不要在旧系统中设置 `Email` 字段。 4. **执行迁移** - 将数据库表导入到目标数据库中。 - 执行 `update-database` 命令进行数据更新。 **其他建议** - 在迁移之前备份数据库。 - 使用日志记录迁移过程。 - 针对数据库中存在的特殊情况进行特殊处理。 - 仔细测试迁移过程。 **注意** - 将旧系统中的字段与新系统中的字段进行匹配,确保数据完整。 - 处理与多租户管理相关的字段时,要特别注意。 - 确保迁移过程顺利完成。

正文

前言

使用 ABP vNext(下文简称 ABP)时,通常都是从 cli 开始新建模板,从一个空项目开始。对已经存续的项目来说,现有的数据,特别是用户等核心数据需要进行迁移。

老的项目,随着规模越来越大,每次修改都需要更改非常多地方,最重要的是,共用数据库使得维护起来需要小心翼翼。为了后续维护方便,我们可以使用 ABP 进行拆分,并将一个个子功能拆成独立的解决方案,独立进行部署。

数据库基于 postgresql。

迁移数据库

老系统建立于 ASP. NET CORE 3.1 时代,使用的是 ASP. NET Identity 这个东西,而 ABP 的用户管理系统也是基于 ASP. NET Identity 的,因此理论上来说可以平滑迁移。
有关用户权限与角色的一共有三个表:

  • AbpUserRoles:记录用户与角色的映射
  • AbpUsers :用户表
  • AbpRoles:角色表

实际上数据库表还是有一些区别,并不能直接进行平滑迁移,举几个例子:

  1. ABP 的 Id 字段为 uuid 类型,Identity 为 string 类型。
  2. ABP 多了一些与多租户管理相关的字段。
  3. ABP 多了一些的标识默认的字段,并且不可为 null。
  4. ABP 7.2中用户表的 Email 是不可为空列,而老版的 Identity 并不是(新版的也是)。

需要先对 User 和 Role 进行同步,然后再同步映射表。先将原来系统内的数据导出为 SQL,直接执行同步语句以同步 User 表:

INSERT INTO "public"."AbpUsers"("Id", "UserName", "NormalizedUserName", "Email", "NormalizedEmail", "EmailConfirmed", "PasswordHash", "SecurityStamp", "ConcurrencyStamp", "PhoneNumber", "PhoneNumberConfirmed", "TwoFactorEnabled", "LockoutEnd", "LockoutEnabled", "AccessFailedCount") VALUES ('a9700c52-448c-bc3a-277bc95c15cb', 'USRDEMO', 'USERDEMO', NULL, NULL, 'f', 'AQAAAAEAACcQHnDh6dl+2xH9ld+XTlqKWQZNaBzhOXIAEzdQ', 'XXOBEMERW572TSLVMBSX56XI7LF', '4dad1c39-7c7e-466c-02b5d75bb006', NULL, 'f', 'f', NULL, 't', 0);

肯定是不能正常通过的,提示 Email 不能为空。

处理 Email 字段

在 2019 年之前,Email 字段还不是必填项目,后来改成了的必填的项。但是这个习惯不是很符合国人的习惯,很多系统有个手机号也能注册。

我翻到了 github 上面的一个 issue,作者给出了以下解决方案:

  • 首先修改数据库表格定义,确保数据库能够接受 null 值。
modelBuilder.Entity<IdentityUser>(entity =>
{
        entity.Property(p => p.Email).IsRequired(false);
        entity.Property(p => p.NormalizedEmail).IsRequired(false);
});
  • 其次修改 IdentityUserStore,在处理用户时,不会对 null 值弹出异常。(找一下哪个引用了 AbpIdentityDomainModule,通常在领域模块)
    [Dependency(ReplaceServices = true)]
    public class MyIdentityUserStore: IdentityUserStore
    {
        public MyIdentityUserStore(IIdentityUserRepository userRepository, IIdentityRoleRepository roleRepository, IGuidGenerator guidGenerator, ILogger<IdentityRoleStore> logger, IdentityErrorDescriber describer = null) : base(userRepository, roleRepository, guidGenerator, logger, describer)
        {
        }

        /// <summary>
        /// Sets the <paramref name="email" /> address for a <paramref name="user" />.
        /// </summary>
        /// <param name="user">The user whose email should be set.</param>
        /// <param name="email">The email to set.</param>
        /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken" /> used to propagate notifications that the operation should be canceled.</param>
        /// <returns>The task object representing the asynchronous operation.</returns>
        public override Task SetEmailAsync(IdentityUser user, string email, CancellationToken cancellationToken = new CancellationToken())
        {
            cancellationToken.ThrowIfCancellationRequested();

            Check.NotNull(user, nameof(user));
            var t = typeof(IdentityUser);
            t.GetProperty(nameof(IdentityUser.Email))
                .SetValue(user, email, null);

            return Task.CompletedTask;
        }
    }

	public override void ConfigureServices(ServiceConfigurationContext context)
	{
	        ...
	       context.Services.Replace(ServiceDescriptor.Scoped<IdentityUserStore, MyIdentityUserStore>());
	}

处理其他字段

其他字段主要是一个默认值的问题,直接设置就可以了:

            entity.Property(p => p.IsActive).HasDefaultValue(true);
            entity.Property(p => p.CreationTime).HasDefaultValue(DateTime.Now);

处理完这个表之后的,执行 update-database,就可以正常执行 SQL 插入了。按照同样的方法处理 AbpRoles 表,最后同步 AbpUserRoles 就完成了。

其实我推荐另外一种方法:直接在数据库上设置默认值,然后导入,最后恢复原来的表结构,这样还不容易有副作用。

验证

启动 Auth 项目(如果是 Tired),用原来的用户名与密码调用,得到以下结果,完成迁移。

image

与迁移现有用户数据到ABP vNext相似的内容:

迁移现有用户数据到ABP vNext

## 前言 使用 ABP vNext(下文简称 ABP)时,通常都是从 cli 开始新建模板,从一个空项目开始。对已经存续的项目来说,现有的数据,特别是用户等核心数据需要进行迁移。 老的项目,随着规模越来越大,每次修改都需要更改非常多地方,最重要的是,共用数据库使得维护起来需要小心翼翼。为了后续维护

无需重新学习,使用 Kibana 查询/可视化 SLS 数据

现在通过 SLS 的 ES 兼容能力,可以很方便地实现用 Kibana 来查询和可视化 SLS 的数据。对于从 ES 迁移到 SLS 的用户可以继续保留原来的 Kibana 使用习惯。下面来演示如何通过 Kibana 来访问 SLS。

php+sql后台实现从主表迁出至副表(数据超万条)

上万条甚至上百万数据进行迁出做备份或者进行不妨碍原系统数据的操作,现在很多企业都会用到,目前就需要将上百万条数据进行迁出到副表保存并操作,直接再后台写一个按钮进行操作,既方便操作也不会很慢。毕竟是客户需要,不能每次迁出都要客户去数据库操作,操作的不好那数据危险度挺高的。 1、分页查询数据库主表数据

OceaBase 分区表创建技巧

最近遇在干个核心的金融项目,规模很大,客户主要是用oracle数据库,现在需要适配ob,原来在oracle就是分区表的迁来ob以后需要进行改造。 oracle默认使用是堆表(ht),而ob使用的是索引组织表(iot),表原理不一样所以分区表会稍微有点区别。 1、表无主键,创建范围分区表 CREATE

EF Core从TPH迁移到TPT

Intro EF Core支持多种方式处理具有继承关系的表,现在支持TPH、TPC(EF Core 7)、TPT,具体的实现方式可以参考官方文档和这篇文章。 大致总结一下不同的方式的区别: TPH:所有的类型都放在一张表中,使用discriminator字段用以区别不同的类型 TPT:不同的子类型有

[转帖]关于华为产品生命周期

关于企业级产品都有EOL里程碑,因些需要考虑对已购产品、业务的生命周期进行升级、迁移、替换等统筹规划。另外如果遇到产品、业务整体出售,还需要评估对现有资产的影响等不可控因素。 今天聊聊华为产品的生命周期,点击查看原文 华为产品生命周期关键里程碑: 华为软件版本生命周期关键里程碑: 点击查询华为产品生

问题记录:VMware vSphere vCenter 6.7 虚拟机迁移失败

问题记录:VMware vSphere vCenter 6.7 虚拟机迁移失败 环境说明: VC版本:VMware vSphere vCenter 6.7 ESXi版本:VMware vSphere ESXi 6.7 问题现象: 迁移虚拟机到别的ESXi主机时报错:vMotion失败。查看信息故障点

Django更换数据库和迁移数据方案

前言 双十一光顾着买东西都没怎么写文章,现在笔记里还有十几篇半成品文章没写完… 今天来分享一下 Django 项目切换数据库和迁移数据的方案,网络上找到的文章方法不一,且使用中容易遇到各类报错,本文根据 Django 官方文档和工作中的经验,稳定可靠,在博客中长期更新~ 如果你遇到同样的问题,阅读本

[转帖]rclone将本地文件或文件夹导入minio中

1、背景:公司数据迁移涉及到文件迁移,原有文件服务器没有使用minio,但是现在的新系统使用了minio。所以这就需要我们将文件上传到minio文件服务器中;由于历史文件数据量大,甲方要求可以通过服务器文件拷贝方式迁移文件,性能、安全性更高; 2、前期准备: 1)minio文件服务器已经安装完成;

.NET6 + EF Core + MySQL 创建实体和数据库、EFCore 数据迁移

前言 接上期文章《.NET6项目连接数据库方式方法》,有人问了我几个问题,现在就这几个问题,拓展延申一下创建实体类、数据库。把ORM框架和数据迁移都写进去。 安装ORM框架,这里我们采用EFCore 安装EFCore 我的项目是在Linux上创建的,使用的是vscode开发工具远程开发。为了方便大家