2011-08-22 15 views
17

Tengo una jerarquía de clases que quiero asignar a varias tablas con Entity Framework 4.1 Code First. Es como tabla por tipo (TPT) pero también quiero una columna de discriminador.¿Puedo especificar una columna de discriminador con una asignación de tabla por tipo?

La jerarquía se ve algo como:

public class Event 
{ 
    public Guid Id { get; set; } 
    public string Code { get; set; } // discriminator 
    public DateTime Date { get; set; } 
} 

public class Party : Event 
{ 
    public int AttendeeCount { get; set; } 
} 

public class BirthdayParty : Party 
{ 
    public int Age { get; set; } 
} 

public class WeddingParty : Party 
{ 
    public string Surname { get; set; } 
} 

Este es un ejemplo bastante débil, pero espero que tenga sentido. Habrá una tabla de "Eventos", una tabla de "Partes" y una tabla para cada tipo de fiesta. Sin embargo, la columna del discriminador ("Código") tendrá un valor conocido para cada tipo de evento, como "NACIMIENTO" para fiestas de cumpleaños o "BODA" para fiestas de bodas.

La idea es que si consulto solo las fiestas de cumpleaños en una fecha determinada, EF sabría agregar Code = 'BIRTH' a mi consulta en lugar de hacer un montón de UNIONs y JOIN para determinar qué filas necesita.

puedo asignar las clases de nivel más bajo de esta manera:

var bd = modelBuilder.Entity<BirthdayParty>(); 
bd.ToTable("BirthdayParties"); 
bd.Property(p => p.Age).HasColumnName("BirthdayAge"); 

ahora tengo que especificar el valor discriminador de allí de alguna manera. He intentado esto:

modelBuilder.Entity<Event>().Map<BirthdayParty>(cfg => 
    { 
     cfg.Requires("Code").HasValue("BIRTH"); 
    }); 

... pero que se queja de que no he especificado el nombre de la tabla dentro de la llamada a Map. Así que he intentado mover la llamada en ToTable allí:

var bd = modelBuilder.Entity<BirthdayParty>(); 
bd.Property(p => p.Age).HasColumnName("BirthdayAge"); 

modelBuilder.Entity<Event>().Map<BirthdayParty>(cfg => 
    { 
     cfg.Requires("Code").HasValue("BIRTH"); 
     cfg.ToTable("BirthdayParties"); 
    }); 

... y ahora se piensa que quiero una columna "Código" de la tabla "BirthdayParties", lo cual no es correcto. Ya le dije que la columna "Código" está en la tabla "Eventos".

¿Esto es posible? ¿Puedo combinar el uso de una columna de discriminación con una asignación de tabla por tipo?

Respuesta

8

Desafortunadamente esto no es compatible. La columna Discriminador se puede usar solo en TPH. TPT difiere los tipos de entidad por tablas mapeadas y siempre produce esas terribles consultas. Podría ser una buena característica, por lo que quizás la sugerencia en Data UserVoice la implemente un día.

actualización

Ya hay una sugerencia de voz del usuario para este titulado "Discriminator column support in TPT inheritance".

0

Hice una anulación en SaveChanges para lograr algo similar. Simplemente agregué un atributo a la clase abstracta llamada Descriminador y lo configuré en base al Nombre de la Clase Concreto cada vez que se agrega algo nuevo.

public class MyContext : DbContext 
{   
    public override int SaveChanges() 
    { 
     foreach (var item in ChangeTracker.Entries().Where(x=>x.Entity is MyAbstractClass && x.State == EntityState.Added)) 
     { 
      ((MyAbstractClass)item.Entity).Descriminator = item.Entity.GetType().Name; 
     } 
     return base.SaveChanges(); 
    } 
} 
Cuestiones relacionadas