我正在使用Entity Framework 4.3,首先是代码迁移和手动迁移。我正在尝试映射使用两个自定义鉴别器字段的TPH(每层次表)设置。一个用于鉴别器本身,另一个用于软删除(很像NH类映射中的“where”选项)。完全相同的设置在另一个在EF 4.2上运行的项目中运行良好。
尝试使用NuGet控制台中的“add-migration”命令添加迁移时出现错误。我已经尝试了定义表名的所有组合 - 类的属性,“OnModelCreating”方法,EntityTypeConfiguration类等。我之前没有涉及复杂层次结构映射的迁移工作得很好。
我偶然发现了EF 4.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
答案 0 :(得分:12)
这是4.3和4.3.1的已知问题。 (我们发现将修复程序放在4.3.1中为时已晚。)幸运的是,有一种相当简单的方法可以更改代码,使其工作。
简而言之,您曾经能够在4.1中的单个EntityConfiguration上进行链式地图调用。和4.2。像这样的模式:
modelBuilder.Entity<Parent>()
.Map<Foo>(...)
.Map<Bar>(...);
这在4.3中不起作用,而是必须在该实体的EntityConfiguration上进行每个Map调用。所以这样的模式:
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");
});
}
(我删除了一些通用参数,因为它们不需要,但这并不重要。)
使用显式的EntityConfigurations执行此操作,您将使用以下内容:
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");
});
}
}
然后
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations
.Add(new ParentConfiguration())
.Add(new FooConfiguration())
.Add(new BarConfiguration());
}
我们计划在5.0中修复此问题。