9

私はEntity Framework 4.3をコードで最初に使用し、手動で移行しています。私は、2つのカスタムdiscriminatorフィールドを使用するTPH(階層ごとのテーブル)設定をマップしようとしています。 1つは弁別子そのものとソフト削除のためのものです(NHクラスマッピングの "where"オプションによく似ています)。まったく同じ設定は、EF 4.2で動作する別のプロジェクトでうまく動作します。Entity Framework 4.3 - TPHマッピングと移行エラー

NuGetコンソールで「add-migration」コマンドを使用して移行を追加しようとすると、エラーが発生します。私はEntityTypeConfigurationクラスなどで、OnModelCreatingメソッドでクラスの属性を定義するすべての組み合わせを試しました。複雑な階層マッピングを伴わなかった以前のマイグレーションはうまくいきました。

私が遭遇したEF4.3にいくつかの大きな変化がありますか?

コード:

//---- Domain classes --------------------- 

public abstract class ParentClass 
{ 
    public string ParentString { get; set; } 
} 

public class Foo : ParentClass 
{ 
    public string FooString { get; set; } 
} 

public class Bar : ParentClass 
{ 
    public string BarString { get; set; } 
} 

//---- Mapping configuration -------------- 

public class ParentConfiguration : EntityTypeConfiguration<ParentClass> 
{ 
    public ParentConfiguration() 
    { 
     Map<Foo>(m => 
     { 
      m.Requires("IsActive").HasValue(1); 
      m.Requires("Type").HasValue("Foo"); 
     }) 
     .ToTable("Parent"); 

     Map<Bar>(m => 
     { 
      m.Requires("IsActive").HasValue(1); 
      m.Requires("Type").HasValue("Bar"); 
     }) 
     .ToTable("Parent"); 
    } 
} 

//---- Context ---------------------------- 

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Configurations.Add(new ParentConfiguration()); 
} 

エラー:

System.InvalidOperationException: The type 'Foo' has already been mapped to table 'Parent'. Specify all mapping aspects of a table in a single Map call. 
    at System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.AddMappingConfiguration(EntityMappingConfiguration mappingConfiguration) 
    at System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.ReassignSubtypeMappings() 
    at System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo) 
    at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection) 
    at System.Data.Entity.Infrastructure.EdmxWriter.WriteEdmx(DbContext context, XmlWriter writer) 
    at System.Data.Entity.Migrations.Extensions.DbContextExtensions.<>c__DisplayClass1.<GetModel>b__0(XmlWriter w) 
    at System.Data.Entity.Migrations.Extensions.DbContextExtensions.GetModel(Action`1 writeXml) 
    at System.Data.Entity.Migrations.Extensions.DbContextExtensions.GetModel(DbContext context) 
    at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration, DbContext usersContext) 
    at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration) 
    at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.GetMigrator() 
    at System.Data.Entity.Migrations.Design.ToolingFacade.GetPendingMigrationsRunner.RunCore() 
    at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.Run() 

Mihkel

答えて

12

これは、4.3と4.3.1の既知の問題です。 (私たちは4.3.1に修正を加えるのが遅すぎることを発見しました)幸運なことに、あなたのコードを変更して動作させるにはかなり簡単な方法があります。

簡潔に言えば、4.1では、単一のEntityConfigurationでチェーンマップ呼び出しを行うことができました。 4.2。このパターンのような何か:

modelBuilder.Entity<Parent>() 
    .Map<Foo>(...) 
    .Map<Bar>(...); 

これは4.3で動作しません、代わりにあなたはそのエンティティのためEntityConfiguration上の各マップ呼び出しを行う必要があります。だから、パターン、このような何か:

modelBuilder.Entity<Foo>() 
    .Map<Foo>(...); 

modelBuilder.Entity<Bar>() 
    .Map<Bar>(...); 

は、特にあなたのケースを取るが、これは動作するはずです:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<ParentClass>() 
     .ToTable("Parent"); 

    modelBuilder.Entity<Foo>() 
     .Map(m => 
       { 
        m.Requires("IsActive").HasValue(1); 
        m.Requires("Type").HasValue("Foo"); 
       }); 

    modelBuilder.Entity<Bar>() 
     .Map(m => 
       { 
        m.Requires("IsActive").HasValue(1); 
        m.Requires("Type").HasValue("Bar"); 
       }); 
} 

(彼らを必要としないので、私は、一般的なパラメータのいくつかを削除したが、それはです

public class ParentConfiguration : EntityTypeConfiguration<ParentClass> 
{ 
    public ParentConfiguration() 
    { 
     ToTable("Parent"); 
    } 
} 

public class FooConfiguration : EntityTypeConfiguration<Foo> 
{ 
    public FooConfiguration() 
    { 
     Map(m => 
     { 
      m.Requires("IsActive").HasValue(1); 
      m.Requires("Type").HasValue("Foo"); 
     }); 
    } 
} 

public class BarConfiguration : EntityTypeConfiguration<Bar> 
{ 
    public BarConfiguration() 
    { 
     Map(m => 
     { 
      m.Requires("IsActive").HasValue(1); 
      m.Requires("Type").HasValue("Bar"); 
     }); 
    } 
} 
:あなたはこのようなものを使用することになり、この使用して明示的なEntityConfigurationsをしていない重要な)

次に

5.0で修正する予定です。

+0

ありがとう、これは私が欲しかったものです。そして、奇妙なやり方で、各サブタイプのための1つの構成が正しいと感じます。下位互換性は素晴らしいですが、将来のリリースで修正されることを願っています。 – Mihkel

+2

これは3年遅れていますが、 'Map(m => m.Requires ...')は '' ToTable( "テーブル名") 'の呼び出しが終わったら**動作します。エンティティフレームワーク6.1.3 btw –

関連する問題