9

Estoy utilizando Entity Framework 4.3 con el código primero y migraciones manuales. Intento mapear una configuración TPH (tabla por jerarquía) que usa dos campos de discriminador personalizados. Uno para el discriminador en sí y el otro para las eliminaciones suaves (muy parecido a la opción "donde" en las asignaciones de la clase NH). La misma configuración funciona bien en otro proyecto que se ejecuta en EF 4.2.Entity Framework 4.3 - Mapeo TPH y error de migración

Me sale el error al intentar agregar una migración usando el comando "add-migration" en la consola NuGet. He intentado todas las combinaciones de definir el nombre de la tabla - atributos en la clase, en el método "OnModelCreating", en las clases EntityTypeConfiguration, etc. Mis migraciones previas que no implicaron mapeos de jerarquías complejas han funcionado bien.

¿Hay algún cambio de rotura en EF 4.3 con el que me he tropezado?

el código:

//---- 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()); 
} 

El error:

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

Respuesta

12

Este es un problema conocido con 4.3 y 4.3.1. (Encontramos que es demasiado tarde para poner la solución en 4.3.1.) Afortunadamente, hay una manera bastante simple de cambiar el código que debería hacer que funcione.

En pocas palabras, solía poder hacer llamadas de mapas encadenadas en una única EntityConfiguration en 4.1. y 4.2. Algo parecido a este patrón:

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

esto no funciona en 4.3 y en lugar de tener que hacer cada llamada Mapa en una EntityConfiguration para esa entidad. Así un patrón algo como esto:

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

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

Tomando su caso concreto, esto debería funcionar:

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"); 
       }); 
} 

(He quitado algunos de los parámetros genéricos, ya que no son necesarios, pero eso es . no es importante)

Haciendo esto utilizando EntityConfigurations explícitas que usaría algo como esto:

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"); 
     }); 
    } 
} 

Y luego

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

Tenemos previsto arreglar esto en 5.0.

+0

Gracias, esto hace justo lo que yo quería. Y de una manera extraña se siente bien - más explícita - una configuración para cada subtipo. Aunque la compatibilidad con versiones anteriores sería agradable y espero que esto se solucione en versiones futuras. – Mihkel

+2

Esto es 3 años tarde, pero las llamadas a 'Map (m => m.Requires ...' solo funcionarán si se hace ** ANTES ** de llamadas a 'ToTable (" table name ")'. Estoy en Entity Framework 6.1.3 por cierto. –

Cuestiones relacionadas