2011-08-22 5 views
17

Mam hierarchii klas, które chcę mapować na kilku tabel przy użyciu Entity Framework 4.1 Code First. To jest jak stół-na-typ (TPT), ale chcę również kolumny dyskryminacyjnej.Czy mogę określić kolumnę dyskryminatora z mapowaniem typu tabela-na-typ?

Hierarchia wygląda mniej więcej tak:

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

Jest to dość słaby przykład, ale mam nadzieję, że to ma sens. Pojawi się tabela "Wydarzenia", tabela "Strony" i tabela dla każdego rodzaju imprezy. Jednak kolumna dyskryminująca ("Kod") będzie miała znaną wartość dla każdego rodzaju wydarzenia, np. "URODZINY" na przyjęcia urodzinowe lub "WEDDING" na przyjęcia weselne.

Chodzi o to, że jeśli zapytam tylko o przyjęcie urodzinowe w określonym dniu, EF będzie chciał dodać Code = 'BIRTH' do mojego zapytania, zamiast robić wiązkę UNION-ów i JOIN-ów, aby ustalić, które wiersze będą potrzebne.

mapować moje zajęcia najniższym poziomie tak:

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

Teraz trzeba określić wartość dyskryminatora tam jakoś. Próbowałem to:

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

... ale narzeka, że ​​nie podano nazwy tabeli wewnątrz wywołania Map. Spróbowałem więc przeniesienie połączenia ToTable się tam:

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

... a teraz myśli, że chce „kod” kolumna w tabeli „BirthdayParties”, co nie jest poprawne. Powiedziałem już, że kolumna "Kod" znajduje się w tabeli "Zdarzenia".

Czy to możliwe? Czy mogę połączyć korzystanie z kolumny dyskryminacyjnej z mapowaniem typu tabela-na-typ?

Odpowiedz

8

Niestety nie jest to obsługiwane. Kolumna dyskryminacyjna może być używana tylko w TPH. TPT różni typy jednostek przez zmapowane tabele i zawsze generuje te straszne zapytania. To może być fajna funkcja, więc może sugestia na Data UserVoice sprawi, że zostanie wdrożony jeden dzień.

Aktualizacja

Istnieje już propozycja na głos użytkownika dla tej zatytułowanej „Discriminator column support in TPT inheritance”.

0

Zrobiłem przesłonięcie na SaveChanges, aby osiągnąć coś podobnego. Po prostu dodałem atrybut do abstrakcyjnej klasy o nazwie Descriminator i ustawię ją w oparciu o nazwę konkretnej klasy za każdym razem, gdy dodawane jest coś nowego.

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