-per-schema。面倒な点は、エンティティマッピングがテーブルを解決するためのスキーマ名を反映する必要があることです。これは、すべてのテナントが同じDBスキーマを使用し、異なるスキーマ名を使用することを前提としています。
私の場合は、適切な接続文字列を使用してDbContextを作成するために、IDbContextFactory
実装を実装して提供することができるので、私が必要としていたものをサポートするために途中で行ったMehdi.me DbContextScopeを使用していました。 2番目のビットでは、テナントのスキーマの詳細がエンティティ設定の初期化に至ることを保証するために、工場の拡張機能を少し構築しました。
あなたのプロジェクトに適しているかどうかを気にせず、必要なものを手に入れるためのアイデアをお気軽にお持ちください。 (https://github.com/StevePy/DbContextScope)
実装では、セットアップのビットをとり、明らかに作業単位のためにDbContextFactory/DbContextLocatorパターンに慣れていますがおおよそ次のセットアップが必要です。
があなたを表現するクラスを作成しますテナント接続の詳細はIDbTenant
を実装しています。このクラスは現在のテナントインスタンスにリンクされます。テナントのテーブルが配置される接続文字列とスキーマ名を返します。
インスタンスを構築するプロジェクトにIDbContextFactory
という実装が実装されています。この工場では、通常、デフォルトコンストラクタ、接続文字列、今作成したIDbTenant
のインスタンスであるステップ1
存在する場合、ステップ2で作成しIDbContextFactory
とDbContextScopeFactory
を初期化するために、あなたのIoCを初期化を受け入れるこれは何かを見てしまいます等:
ioc.Register<IDbContextScopeFactory>(()=> {new DbContextScopeFactory(new SqlServerTenantDbContextFactory());});
SqlServerTenantDbContextFactory
は、上記のステップ2で作成した実装は、おおよそAutofac IoCのための登録プロセスです。本質的には、DbContextScopeFactory
がインスタンス化されることを確実にしたい場合は、DbContextFactory
を指定します。
ContextFactoryの実装です。
public class SqlServerTenantDbContextFactory : IDbContextFactory
{
TDbContext IDbContextFactory.CreateDbContext<TDbContext>()
{
return (TDbContext)Activator.CreateInstance<TDbContext>();
}
TDbContext IDbContextFactory.CreateDbContext<TDbContext>(IDbTenant tenant)
{
var connection = DbProviderFactories.GetFactory("System.Data.SqlClient").CreateConnection();
// based on the provider set up in <providers> configration under <entityFramework>...
connnection.ConnectionString = tenant?.ConnectionString;
return (TDbContext)Activator.CreateInstance(typeof(TDbContext), tenant, connection, true);
}
TDbContext IDbContextFactory.CreateDbContext<TDbContext>(string connectionString)
{
var connection = DbProviderFactories.GetFactory("System.Data.SqlClient").CreateConnection();
connnection.ConnectionString = connectionString;
return (TDbContext)Activator.CreateInstance(typeof(TDbContext), connection, true);
}
}
EntityTypeConfiguration
がIDbTenant
を受け取るコンストラクタを追加し、そのコンストラクタに[ImportingConstructor]
属性を追加するための最後の構成変更があります。 ContextFactoryは残りの部分を処理します。例えば、「注文」と呼ばれるエンティティを与えられたので、次のようなエンティティ型の構成を定義します
public class OrderConfiguration : EntityTypeConfiguration<Order>
{
[ImportingConstructor]
public OrderConfiguration(IDbTenant tenant)
: base()
{
ToTable("Orders", tenant.SchemaName);
// HasKey(...);
// HasMany(...);
// etc. etc. etc.
}
}
わからない、これはコード-最初の実装を提供するように適合させることができ、私はそれ以来、それを疑うだろう場合パターンは、スキーマやサーバー間の切り替えに関して混乱となるdbスキーマ定義と移行の責任を負うことを望んでいます。
Mehdi.me DbContextScopeの以前の経験がない場合は特にそうですが、うまくいけばあなたにいくつかのアイデアを与えるかもしれません。
private MyAppContext Context
{
get { return ContextLocator.Get<MyAppContext>(_tenant); }
}
_tenant:これらを設定すると
、通常Mehdi.meパターンからの唯一の変更は、あなたがDbContextLocator
を使用してコンテキストを取得するために行くとき、それをIDbTenant
インスタンスのインスタンスを渡すことですログインしたテナントに基づいて初期化されます。 (つまり、OWINの認証またはセッション状態から詳細を取得するテナント識別戦略...)ここからコンテキスト・ファクトリが引き継がれ、テナントの詳細を使用してコンテキストが初期化されます。
ランタイムにスキーマを取得することについてはわかりませんが、既存のデータベースに基づいてコンテキストを作成することができますので、アプリケーションに異なるコンテキストを追加して実行時に切り替えることができます。しかし、通常は、指定されたスキーマに基づいてコーディングするので、異なるコンテキストのビジネスクラスを作成し、実行時に切り替えることもできます。 –