2017-10-12 15 views
0

私は現在、ASP.NET MVC 5プロジェクトでEntity Framework 6を​​使用しています。私たちが持っている各クライアントには独自のデータベーススキーマがあります。私が今までに見つけた限り、実行時にEntity Frameworkでスキーマを切り替えることは容易ではありません。私は基本的にcsdlと他のファイルを取得し、スキーマの検索と置換を行うヘルパークラスを作成しましたが、明らかにそれはアプリケーションに大きなパフォーマンスの影響を追加しています。ASP.NET MVC 5 Entity Frameworkの代わりに、実行時にスキーマを指定する機能はありますか?

誰でもEFの実行時にスキーマを変更する方法を知っていますか?サポートされていないか、既に行っていること以外の回避策がない場合は、ORMツールを変更する必要があります。そこにこれをサポートする他のものがありますので、私はデータベースからモデルを生成することができますか?すべてのクラスを最初から作成してマッピングを作成すると、非常に時間がかかります。

ありがとうございます。以下を想定し

+1

ランタイムにスキーマを取得することについてはわかりませんが、既存のデータベースに基づいてコンテキストを作成することができますので、アプリケーションに異なるコンテキストを追加して実行時に切り替えることができます。しかし、通常は、指定されたスキーマに基づいてコーディングするので、異なるコンテキストのビジネスクラスを作成し、実行時に切り替えることもできます。 –

答えて

0

は真である:

    あなたは
  • SQL Serverデータベース
  • を使用している
  • あなたのクライアントのそれぞれが独立したデータベース・ユーザー・アカウントを使用していますあなたはSQLでのユーザーのデフォルトのスキーマを設定することができます

サーバ。その後、

https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-user-transact-sql

How to set the default schema of a database in SQL Server 2005?

そして、各クライアントの実行時にEntity Frameworkの接続文字列を変更します。私は最近、(接続文字列を使用して解決することができます)異なるサーバー上に配置されているだけではないテナントのDBをサポートするだけでなく、テナントをサポートできる信頼性の高いマルチテナント接続を開発するために、この問題に取り組むために必要な

Entity Framework change connection at runtime

0

-per-schema。面倒な点は、エンティティマッピングがテーブルを解決するためのスキーマ名を反映する必要があることです。これは、すべてのテナントが同じDBスキーマを使用し、異なるスキーマ名を使用することを前提としています。

私の場合は、適切な接続文字列を使用してDbContextを作成するために、IDbContextFactory実装を実装して提供することができるので、私が必要としていたものをサポートするために途中で行ったMehdi.me DbContextScopeを使用していました。 2番目のビットでは、テナントのスキーマの詳細がエンティティ設定の初期化に至ることを保証するために、工場の拡張機能を少し構築しました。

あなたのプロジェクトに適しているかどうかを気にせず、必要なものを手に入れるためのアイデアをお気軽にお持ちください。 (https://github.com/StevePy/DbContextScope

実装では、セットアップのビットをとり、明らかに作業単位のためにDbContextFactory/DbContextLocatorパターンに慣れていますがおおよそ次のセットアップが必要です。

  1. があなたを表現するクラスを作成しますテナント接続の詳細はIDbTenantを実装しています。このクラスは現在のテナントインスタンスにリンクされます。テナントのテーブルが配置される接続文字列とスキーマ名を返します。

  2. インスタンスを構築するプロジェクトにIDbContextFactoryという実装が実装されています。この工場では、通常、デフォルトコンストラクタ、接続文字列、今作成したIDbTenantのインスタンスであるステップ1

  3. 存在する場合、ステップ2で作成しIDbContextFactoryDbContextScopeFactoryを初期化するために、あなたの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); 
    } 
} 

EntityTypeConfigurationIDbTenantを受け取るコンストラクタを追加し、そのコンストラクタに[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の認証またはセッション状態から詳細を取得するテナント識別戦略...)ここからコンテキスト・ファクトリが引き継がれ、テナントの詳細を使用してコンテキストが初期化されます。

関連する問題