遷移現有用戶數據到ABP vNext

来源:https://www.cnblogs.com/podolski/archive/2023/06/17/17488270.html
-Advertisement-
Play Games

## 前言 使用 ABP vNext(下文簡稱 ABP)時,通常都是從 cli 開始新建模板,從一個空項目開始。對已經存續的項目來說,現有的數據,特別是用戶等核心數據需要進行遷移。 老的項目,隨著規模越來越大,每次修改都需要更改非常多地方,最重要的是,共用資料庫使得維護起來需要小心翼翼。為了後續維護 ...


前言

使用 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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • # Go 語言之在 gin 框架中使用 zap 日誌庫 ### gin 框架預設使用的是自帶的日誌 #### `gin.Default()`的源碼 Logger(), Recovery() ```go func Default() *Engine { debugPrintWARNINGDefault ...
  • ## 概述 Nginx 是一個高性能的 HTTP 和反向代理伺服器,特點是占用記憶體少,併發能力強 #### 1. 正向代理 如果把區域網外的 Internet 想象成一個巨大的資源庫,則區域網中的客戶端要訪問 Internet,需要通過代理伺服器來訪問,這種訪問就稱為正向代理 ![](https:/ ...
  • # 類和對象 **組成結構** • 構造函數: 在創建對象的時候給屬性賦值 • 成員變數: • 成員方法(函數) • 局部變數 • 代碼塊 ## 構造器 每個類都有一個主構造器,這個構造器和類定義"交織"在一起類名後面的內容就是主構造器,如果參數列表為空的話,()可以省略 scala的類有且僅有一個 ...
  • ## 1.常用命令 `創建項目:django-admin startproject 項目名` `創建APP(進入工程目錄):python manage.py startapp 網站名` `創建庫表(進入工程目錄):python manage.py makemigrations` `執行庫表建立(進入 ...
  • # Go 語言之自定義 zap 日誌 [zap 日誌](https://github.com/uber-go/zap):https://github.com/uber-go/zap ## 一、日誌寫入文件 - `zap.NewProduction`、`zap.NewDevelopment` 是預設配 ...
  • (續前文) ## 9、Service實現類代碼示例 ​ ​ 以用戶管理模塊為例,展示Service實現類代碼。用戶管理的Service實現類為UserManServiceImpl。​UserManServiceImpl除了沒有deleteItems方法外,具備CRUD的其它常規方法。實際上​User ...
  • 本文主要介紹在之家廣告業務系統中運用任務編排治理工具的場景及其可以解決的問題,講解任務編排框架的核心要點,以及向大家演示一個任務編排框架的基本結構,讓大家對任務編排工具增強業務開發效率,提高研發質量有更深刻的理解。 ...
  • # Go 語言之 zap 日誌庫簡單使用 ## 預設的 Go log log:https://pkg.go.dev/log ```go package main import ( "log" "os" ) func init() { log.SetPrefix("LOG: ") // 設置首碼 f, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...