序文
私が実際に遭遇したとき、マルチテナントを実現するためにEFコアの問題を書いたので、この記事を書くための理由。
特定の記事へのリンク:
データから、マルチテナント達成EFコア(1)を使用してAsp.netコア
Asp.netコアEFコアからマルチテナントのデータを使用して達成(2):表分離 (主に関連する話)
マルチテナントテーブルが同じデータベースを使用するので:ここで私が遭遇する主な問題があります。このため、ないDatabase.EnsureCreated(で)自動的に複数の同一の構造が、テーブルの別の名前を作成します。
あなたには、いくつかのマルチテーブルを作成するためのスクリプトを実行する必要があるので、だから私は、本文中で言及しました。
私はまだ、SQL管理テーブルを使用して考えている間、マルチテナントの場合は、より信頼性の高いソリューションですが、EFコアネイティブが提供する移行メカニズムを使用することができれば、実行時に自動的にデータテーブル構造を作成し、更新する、それがより友好的です。
アイデアの実現
実際には、我々はすべて知っている、EFコア(コード最初は)ここでは、データベースに__EFMigrationHistoryにデータベースレコードのバージョンを表のみを生成します。
同時に複数のテナントがあるので、記事このシナリオでは、同じテーブル構造(製品)が同時にデータテーブルテナントの複数のバージョンを記録することはできません__EFMigrationHistoryを意味し、複数回表示されます。
重要な問題は、既に知っているので、まあ、私たちはここに明らかにされた答えを置くことができ、実現について詳細に尋ねました:
store1とMigrationHistoryテーブルのstore2があった一方で、図あなたは、私たちのカスタムMigrationHistoryテーブルを参照し、次のデータですることができます。
インプリメント
プロジェクト
これは、マルチテナントシステムであり、具体的には、テナントに応じて、同一のテーブルにすべてのデータを作成します。
プロジェクトの依存関係:
1. .NETのコアアプリ3.1。マシン上にインストールされている.NETコアSDK、バージョン3.1
2. MySQLの。Pomelo.EntityFrameworkCore.MySql使用パッケージ
3. EFコア、Microsoft.EntityFrameworkCore、バージョン3.1.1。EF core3.0は、.NETの標準的な2.1のためであるので、ここでは3.1を使用する必要があります。
4. EFコア設計、Microsoft.EntityFrameworkCore.Design、バージョン3.1.1
5. DOTNET-EFツール、バージョン3.1.1
キーオブジェクト:
1. MigrationsAssembly、対応するマイグレーションの作成を達成するために、このようなユニットの使用。
2.移行ファイル、ここでは実際にデータベースを作成し、更新するために、特定のファイルを生成しDOTNET-EFコマンドの実装を使用し、移行関連のファイルの基を意味します。
実装手順
1.実行DOTNET-EFコマンドでは、マイグレーション・ファイルを生成します
コマンド:
1 DOTNET - EFの移行は、追加のinit
実行後、より多くの*は.csファイルを生成するには、プロジェクトフォルダ内の移行ファイルは意志、実際に彼らは、実行可能なC#のオブジェクトであります
機関は次のとおりです。
これらの3つの文書には、このファイルの主な機能は、* _init.csです
開封後、我々は彼を変更する必要があります
1 使用Microsoft.EntityFrameworkCore.Metadata。 2 使用Microsoft.EntityFrameworkCore.Migrations。 3 4 名前空間kiwiho.Course.MultipleTenancy.EFcore.Api.Migrations 5 { 6 パブリック部分クラスINIT:移行 7 { 8 プライベート読み取り専用文字列プレフィックス。 9 公共のinit(文字列のプレフィックス) 10 { 11 であれば(string.IsNullOrEmpty(接頭辞)) 12 { 13 投新しいSystem.ArgumentNullException()。 14 } 15 this.prefix = 接頭辞。 16 } 17 18 保護オーバーライドボイドアップ(MigrationBuilder migrationBuilder) 19 { 20 migrationBuilder.CreateTable( 21 名:接頭辞+ "_Products"、 22 列:表は、 => 新しい 23 { 24 イド= 表。列< 整数> (NULL可能:偽) 25 .Annotation( "MySQLの:ValueGenerationStrategy"、MySqlValueGenerationStrategy.IdentityColumn)、 26 名= 表。列<文字列>(maxLengthの:50 、NULL可能:偽)、 27 カテゴリー= 表。列<文字列>(maxLengthの:50 、NULL可能:真)、 28 価格= 表。コラム< ダブル> (NULL可能:真) 29 }、 30の 制約:表 => 31 { 32 表 .PrimaryKey( "PK__Products"、X => x.Id)。 33 }); 34 } 35 36 保護オーバーライドボイドダウン(MigrationBuilder migrationBuilder) 37 { 38 migrationBuilder.DropTable( 39 名:接頭辞+ "_Products")。 40 } 41 } 42 }
ここでの主な変更点は次のとおりです。
1.1コンストラクタを追加し、prefixパラメータの内部を追加します。
1.2アップ方法、テーブル名の変更、可変_Product(ライン21)の前にプレフィックスを追加
1.3ダウン法、テーブル名の変更、可変_Product(ライン39)の前にプレフィックスを追加
MigrationByTenantAssemblyファイルを作成します。2.。
変更前のtell移行ファイルのコンストラクタので、理論的にはEFコアを正常にデフォルトの方法で5つの法の変更の移行ファイルを実行されました
1 使用してシステムを。 2 使用するSystem.Reflectionと、 3 使用Microsoft.EntityFrameworkCoreと、 4 使用Microsoft.EntityFrameworkCore.Diagnostics。 5 使用Microsoft.EntityFrameworkCore.Infrastructureと、 6 使用Microsoft.EntityFrameworkCore.Migrations。 7 使用Microsoft.EntityFrameworkCore.Migrations.Internalと、 8 9 名前空間kiwiho.Course.MultipleTenancy.EFcore.Api.Infrastructure 10 { 11 パブリック クラスMigrationByTenantAssembly:MigrationsAssembly 12 { 13 プライベート 読み取り専用DbContextコンテキスト。 14 15 公共MigrationByTenantAssembly(ICurrentDbContext currentContext、 16 IDbContextOptionsオプション、IMigrationsIdGenerator idGenerator、 17 IDiagnosticsLogger <DbLoggerCategory.Migrations> ロガー) 18 :塩基(currentContext、オプション、idGenerator、ロガー) 19 { 20 コンテキスト= currentContext.Context。 21 } 22 23 公共 オーバーライドマイグレーションCreateMigration(のTypeInfo migrationClass、 24 列activeProvider) 25 { 26 であれば(activeProvider == NULL ) 27 スロー 新しい例外ArgumentNullException($ " {がNameOf(activeProvider)}引数ヌルです" )。 28 29 VAR hasCtorWithSchema = migrationClass 30 .GetConstructor(新しい [] { typeof演算(列)})=!ヌル。 31 32 であれば(hasCtorWithSchema &&コンテキストあるITenantDbContext tenantDbContext) 33 { 34 VARのインスタンス=(移行)Activator.CreateInstance(migrationClass.AsType()、tenantDbContext .TenantInfo?.NAME)。 35 instance.ActiveProvider = activeProvider。 36 リターン・インスタンス。 37 } 38 39 リターン ベース.CreateMigration(migrationClass、activeProvider)。 40 } 41 } 42 }
何も特別なキーは、29〜37行で、このクラスであります。ターゲット・オブジェクトの移行コンストラクタパラメータのみ1つの文字列型が存在するか否かを決定するために最初の必要性
DbContextがあるかどうかを判断するには、ITenantDbContextインターフェイスを実現します。
マイグレーションインスタンスは(コンストラクタにテナント名パス)活性化剤を使用して作成しました
3. AddDatabase MultipleTenancyExtensionクラス、追加のカスタムテーブルの方法MigrationHistory
1 VAR dbOptionBuilder = options.UseMySql(resolver.GetConnection()、ビルダー=> 2 { 3 であれば(option.Type == ConnectionResolverType.ByTabel) 4 { 5 builder.MigrationsHistoryTable($ {tenantInfo.Name} __ EFMigrationsHistory " ); 6 } 7 }); 8 9 10 dbOptionBuilder.ReplaceService <Microsoft.EntityFrameworkCore.Migrations.IMigrationsAssembly、MigrationByTenantAssembly>();
最も重要なポイントは、5行目で、コールMigrationsHistoryTableはMigrationHistoryテーブルを設定します
もう一つのポイントは、MigrationByTenantAssemblyとデフォルト実装EFコア(IMigrationsAssemblyインタフェース)タイプの交換、行10であります
次のように変更ProductControllerのコンストラクタにおいて4.
Database.Migrateの主な役割は、実行時にデータベースを作成および更新するために実装することができます
1 公共ProductController(StoreDbContext storeDbContext) 2 { 3 本 .storeDbContext = storeDbContext。 4 本.storeDbContext.Database.Migrate()。 5 }
結果を表示
コール・インタフェース
一連の記事のように、私たちの最初の呼び出しでは、製品のインタフェースがstore1レコードとstore2で追加された作成されます。
次はstore1の結果であります
store2のクエリ結果
データを検証するために、データベースをチェック
データベースのテーブル構造
store1_Productsテーブルデータ
store2_Productsテーブルデータ
概要
この記事では、コードの最初のモードでEFコアは、データベースを更新する方法を説明し、そしてコンストラクタ移行オブジェクトを追加することによって、自分の必要なパラメータを追加します。
IMigrationsAssembly実施既定を置換することによりEFコアは、カスタムオブジェクトのMigrationByTenantAssembly移行がインスタンス化されます。
EFコアMigrationHistoryが最終的に要求し、デフォルトを交換してください。
が、この記事では一例ですが、それは達成するために、実際のプロジェクトのニーズに同じツールを使用することができます。しかし、その後、再び、マルチテナント例のために、私はデシベル最初のモードを使用することをお勧めします。
コードについて
コードはgithubの上で渡された、支店コードEF_code_firstを参照してください。
https://github.com/woailibain/EFCore.MultipleTenancyDemo/tree/EF_code_first