2015-09-08 14 views
14

スキーマ名が移行コードに含まれているため、Oracleデータベースを対象としたEntity Frameworkの移行を使用する際に問題があり、スキーマ名もユーザー名です。私の目標は、スキーマに依存しないCode First Migrations(テスト環境と本番環境用に1組の移行を行うことができるようにすること)です。スキーマに依存しないエンティティフレームワークコードの最初の移行

私はすでに(Entity Frameworkの6.1.3を使用して)このアプローチを試してみました:

1)私は、Web.configファイルでスキーマ名を持っている:

<add key="SchemaName" value="IPR_TEST" /> 

2)私のDbContextはとしてスキーマ名を取りますコンストラクタのパラメータ:

public EdistributionDbContext(string schemaName) 
    : base("EdistributionConnection") 
{ 
    _schemaName = schemaName; 
} 

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.HasDefaultSchema(_schemaName); 
} 

3)私は、パラメータなしのコンストラクタを持っていない私のDbContextを作成できるようにEntity Frameworkの移行のためのIDbContextFactoryを実装する必要がありました:

public class MigrationsContextFactory : IDbContextFactory<EdistributionDbContext> 
{ 
    public EdistributionDbContext Create() 
    { 
     return new EdistributionDbContext(GetSchemaName()); 
    } 
} 

4)私はまた、正しいスキーマ内に配置される移行履歴表を構成:

public class EdistributionDbConfiguration : DbConfiguration 
{ 
    public EdistributionDbConfiguration() 
    { 
     SetDefaultHistoryContext((connection, defaultSchema) 
      => new HistoryContext(connection, GetSchemaName())); 
    } 
} 

5)Iは、ハードコードスキーマ名を置換する移行用に生成されたコードを修正しました。例えば。私はCreateTable("IPR_TEST.Users")CreateTable($"{_schema}.Users")に置き換えました。 (_schemaフィールドはWeb.configの値に従って設定されます)。

6)私はMigrateDatabaseToLatestVersion<EdistributionDbContext, MigrationsConfiguration>()データベース初期設定を使用します。

この設定をすべて行っても、別のスキーマ(web.config変換など)に切り替えると問題は残っています。データベースが自分のモデルと一致せず、AutomaticMigrationsが無効になっているという例外がスローされます。希望)。私は新しいマイグレーションが発生したadd-migrationを実行しようとすると、すべてのオブジェクトが別のスキーマに移動しなければならない場所(例:。確かに望まれていないMoveTable(name: "IPR_TEST.DistSetGroups", newSchema: "IPR");、私にとって

は、そのスキーマ名がハードワイヤードモデル文字列のどこかにあるようですマイグレーションクラスで-hash(例えば201509080802305_InitialCreate.resx。)、すなわち:そこ

<data name="Target" xml:space="preserve"> 
    <value>H4sIAAAAAAAEAO09227jO... </value> 
</data> 

これは、スキーマ名を無視するように、コードファーストの移行を指示する仕方

+0

これを試したことがありますが、SQLサーバーでモデルバインディングでスキーマを指定しないと、ユーザーの既定のスキーマだけが使用されます。 –

+2

ありがとうございます@ベン、あなたのコメントは私の問題の解決につながる可能性があります。 'modelBuilder.HasDefaultSchema(" SCHEMA_NAME ");を省略すると、Entity Frameworkはデフォルトのスキーマとして" dbo "を設定します。しかし、今では 'modelBuilder.HasDefaultSchema(string.Empty);'を試しましたが、ユーザーのデフォルトスキーマが(正しく)使用されているようです。残念ながら、移行のSQLを生成するために使用される 'Oracle.ManagedDataAccess.EntityFramework.OracleMigrationSqlGenerator'は、' string.Empty'-schema-nameに問題があり、移行のSQLを生成するときに例外をスローします...しかし、それは別の問題です... –

+0

こんにちはJan Palas、この問題についての解決策はありますか?私は同じ問題を抱えていますが、私はOracleでEF Migrationを使用しています。スキーマを変更すると、すべての移行スクリプトにMoveTableが含まれています... – toregua

答えて

1

あなたが派生DbContextと「オーバーライドを作成することができますか? "modelBuilder.HasDefaultSchema(...) in OnModelCreating

public class TestDbContext : ProductionDbContext 
{ 
    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 

     modelBuilder.HasDefaultSchema("TestSchema"); 
    } 
} 

次に、両方のコンテキストの移行を作成できます。 1つのプロジェクトで2つの移行を作成する方法については、this questionを参照してください。

このアプローチの欠点は、2つの別々の移行を維持する必要があることです。ただし、TestDbContextの設定を調整する機会があります。

1)私は、Webでのスキーマ名を持っている:

1

は私が最終的にはかなりよく働くようで解決策を見つけ、同じ問題とあなたのaproachのおかげに直面していました。設定アプリの設定:

public class HistoryDbContext : HistoryContext 
{ 
    internal static readonly string SCHEMA; 

    static HistoryDbContext() 
    { 
     SCHEMA = ConfigurationManager.AppSettings["Schema"]; 
    } 

    public HistoryDbContext(DbConnection dbConnection, string defaultSchema) 
      : base(dbConnection, defaultSchema) 
    { } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 
     modelBuilder.HasDefaultSchema(SCHEMA); 
    } 
} 

3)私は私の履歴デシベルコンテキスト参照するDBの構成があります:私は歴史の文脈持っ

<add key="Schema" value="TEST" /> 

2)

public class MyDbConfiguration : DbConfiguration 
{ 
    public MyDbConfiguration() 
    { 
     SetDefaultHistoryContext((connection, defaultSchema) => new HistoryDbContext(connection, defaultSchema)); 
    } 
} 

4)そして、これは私のdbコンテキストです:

public partial class MyDbContext : DbContext 
{ 
    public MyDbContext() 
     : base("name=MyOracleDbContext") 
    { } 

    public static void Initialize() 
    { 
     DbConfiguration.SetConfiguration(new MyDbConfiguration()); 
     Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyDbContext, Migrations.Configuration>()); 
    } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.HasDefaultSchema(string.Empty); 
    } 
} 

5 )最後に、私は鍵がString.EmptyのdBのコンテキストと正しいものに歴史の文脈のスキーマのデフォルトのスキーマを設定することです

protected void Application_Start() 
{ 
    MyDbContext.Initialize(); 
} 

のGlobal.asaxからInitializeメソッドを呼び出します。 したがって、移行を作成するときはスキーマに依存しません。移行のresxのDefaultSchema変数は空白になります。しかし、履歴のDBコンテキスト・スキーマは、移行検査が合格するのを許容するのは正しいです。

私は、次のnugetsパッケージを使用しています:

<package id="EntityFramework" version="6.2.0" targetFramework="net452" /> 
<package id="Oracle.ManagedDataAccess" version="12.2.1100" targetFramework="net452" /> 
<package id="Oracle.ManagedDataAccess.EntityFramework" version="12.2.1100" targetFramework="net452" /> 

あなたはその後、別のデータベースに成功したOracleの移行を使用することができます。

+0

動作確認済みです。スキーマ名をHistoryDbContextにのみ設定することは、違いを生み出す違いであり、すべてを適所にスナップします。あなたが流暢な設定/データアノテーションを使用し、このアプローチを採用したい場合は、あなたの流暢な設定/データアノテーションのどこにでもスキーマ名を設定しないようにする必要があるという事実を強調したいと思います。スキーマ名を空の文字列のままにしてください)。 – xDisruptor

関連する問題