Asp.Net CoreでマルチDbContextを作成し、データベースに移行

7834 ワード

私たちのプロジェクトでは、私たちのプロジェクトでDbContextを作成する必要がある場合があります.また、これらのDbContextの間には明らかな境界があります.例えば、システム内の2つのDbContextの1つはデータベース全体の権限に関連するコンテンツであり、もう1つのDbContextは主にボリュームビジネスに関連するコンテンツであり、この2つの部分は互いに分離することができます.このとき、私たちのプロジェクトで2つの異なるDbContextを作成し、それぞれ注入することができます.もちろん、この2つのDbContextは1つのConnectionStringを共有することができます.また、異なるDbContextを使用することもできます.これは、異なるニーズに応じて決定する必要があります.私たちが異なるDbContextを構築したとき、DbContextの変更内容をそれぞれデータベースに移行する必要があります.これはデータベースMigrationの問題に関連しているので、記事全体では主に複数のDbContextと各DbContextのMigrationを作成する方法について説明します. 
次に、2つの異なるDbContextをコードで作成します.
1 AuthorityDbContextの作成
public class AuthorityDbContext : AbpZeroDbContext {
        /* Define a DbSet for each entity of the application */

        public DbSet UserMappings { get; set; }

        public SunlightDbContext(DbContextOptions options)
            : base(options) {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder) {
            base.OnModelCreating(modelBuilder);
            modelBuilder.ApplyConfiguration(new TenantConfiguration());

            //                   Model   ,          

            if (Database.IsInMemory())
                return;            
        }
       
    }

このDbContextは主に認証と権限に関する操作に使用されます.ここでは最も簡単な構造を定義しています.後のDbContextは具体的なビジネスに関する内容です.私たちのプロジェクトでは、2つのDbContextは同じ接続文字列を使用します.
2 IDesignTimeDbContextFactoryインタフェース実装
 /// 
    ///    EF Core Migration     DbContext,          XXX.Dcs.WebHost    appsettings.json
    /// 
    public class AuthorityDesignTimeDbContextFactory : IDesignTimeDbContextFactory {
        private const string DefaultConnectionStringName = "Default";

        public SunlightDbContext CreateDbContext(string[] args) {
            var configuration = AppConfigurations.Get(WebContentDirectoryFinder.CalculateContentRootFolder());
            var connectString = configuration.GetConnectionString(DefaultConnectionStringName);

            var builder = new DbContextOptionsBuilder();
            builder.UseSqlServer(connectString);
            return new SunlightDbContext(builder.Options);
        }
    }

このコードを理解する前に、これが何のために使われているのかを理解することができます.注釈のように、EFCore Migrationを使用すると、WebHostプロジェクトのappsettingsがデフォルトで読み込まれます.json内のDefault構成の接続文字列.
{
  "ConnectionStrings": {
    "Default": "Server=XXXX,XX;Database=XXXX;User Id=XXXX;Password=XXXX;",
    "DcsEntity": "Server=XXXX,XX;Database=XXXX;User Id=XXXX;Password=XXXX;"
  },
  "Redis": {
    "Configuration": "127.0.0.1:XXXX",
    "InstanceName": "XXXX-Sales"
  },
  "App": {
    "ServerRootAddress": "http://localhost:XXXX/",
    "ClientRootAddress": "http://localhost:XXXX/",
    "CorsOrigins": "http://localhost:XX,http://localhost:XX,http://localhost:XX"
  },
  "Kafka": {
    "BootstrapServers": "127.0.0.1:XX",
    "MessageTimeoutMs": 5000,
    "Topics": {
      "CustomerAndVehicleEvent": "XXXX-customer-update",
      "AddOrUpdateProductCategoryEvent": "XXXX-add-update-product-category",
      "AddOrUpdateDealerEvent": "XXXX-add-update-dealer",
      "ProductUpdateEvent": "XXXX-product-update",
      "VehicleInformationUpdateStatusEvent": "XXXX-add-update-vehicle-info",
      "AddCustomerEvent": "cowin-add-customer"
    }
  },
  "Application": {
    "Name": "XXXX-sales"
  },
  "AppSettings": {
    "ProductSyncPeriodMi": 60,
    "DealerSyncPeriodMi": 60
  },
  "Eai": {
    "Authentication": {
      "Username": "2XXX2",
      "Password": "XXXX"
    },
    "Services": {
      "SapFinancial": "http://XXXX:XXXX/OSB_MNGT/Proxy/XXXX"
    }
  },
  "DependencyServices": {
    "BlobStorage": "http://XXXX-XXXX/"
  },
  "Authentication": {
    "JwtBearer": {
      "IsEnabled": true,
      "Authority": "http://XXXX/",
      "RequireHttpsMetadata": false
    }
  },
  "Sentry": {
    "IncludeRequestPayload": true,
    "SendDefaultPii": true,
    "MinimumBreadcrumbLevel": "Debug",
    "MinimumEventLevel": "Warning",
    "AttachStackTrace": true
  },
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  }
}

  3 DB Migration
以上の作業があれば、データベースの移行と更新を行うことができます.主なプロセスは2ステップAdd-Migration XXXとUpdate-Database-verboseの2ステップに分けられます.ただ、現在複数のDbContextを構築したいだけです.そのため、パラメータ-c xxddbContextで具体的なDbContextを指定する必要があります.そうしないと、次のエラーが発生します.More than one DbContext was found. Specify which one to use. Use the '-Context' parameter for PowerShell commands and the '--context' parameter for dotnet commands.
これらがあれば、データベースに更新できます.更新時にDbContextを指定することを覚えておいてください.更新時には、Update-Database-verbose-c XXXXXDbContextというコマンドを使用します.
4 2番目のDbContextの作成
前の手順では、2番目のDbContextを作成する手順は簡単です.上記の手順1、2、3を繰り返して、2番目のDbContextの作成とデータベースの移行を完了します.しかし、ここではABPフレームワークのマルチテナント関連のエンティティを使用したいため、ここで構築したベースクラスはAppZerodbContextから継承されている点に注意する必要があります.後で作成したビジネス関連のDbContextの場合、これらは必要ありませんので、AbpDbContextから簡単に継承するだけです.
5 StartupでEF Core DbContextを初期化
これは以前に作成したDbContextとは異なり、Aspに向かう必要がある.Net Coreは注入容器に異なるDbContextを2回注入することに依存し、Asp.Net CoreでDbContextを作成してインプリメンテーションする方法については、ここをクリックして公式ドキュメントを参照してください.ここでは、StartupのConfigureServicesで次のコードを呼び出す必要があります.これは異なるところです.具体的には、コードを見てみましょう. 
//     EF Core DbContext
            var abpConnectionString = _appConfiguration.GetConnectionString("Default");
            services.AddDbContext(options => {
                options.UseSqlServer(abpConnectionString);
                if (Environment.IsDevelopment()) {
                    options.EnableSensitiveDataLogging();
                    // https://docs.microsoft.com/en-us/ef/core/querying/client-eval#optional-behavior-throw-an-exception-for-client-evaluation
                    options.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
                }
            });
            // AuthConfigurer.MapUserIdentity     DbContextOptions
            // Abp DI         ,      
            services.AddTransient(provider => {
                var builder = new DbContextOptionsBuilder();
                builder.UseSqlServer(abpConnectionString);
                return builder.Options;
            });
            var dcsConnectionString = _appConfiguration.GetConnectionString("DcsEntity");
            services.AddDbContext(options => {
                options.UseSqlServer(dcsConnectionString);
                if (Environment.IsDevelopment()) {
                    options.EnableSensitiveDataLogging();
                    // https://docs.microsoft.com/en-us/ef/core/querying/client-eval#optional-behavior-throw-an-exception-for-client-evaluation
                    options.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
                }
            }); 

これにより、サービスの具体的な実行中に具体的なDbContextを追加することができ、上記のプロセスを経て、1つのプロジェクトに複数のDbContextを追加し、データベース全体を移行することができます.
 
転載先:https://www.cnblogs.com/seekdream/p/11459447.html