2016-04-17 16 views
6

Myślę, że jest to możliwe w nhiberate, ale moje pytanie dotyczy Entity Framework.Entity Framework: mapuj wiele klas do jednej tabeli

W moim modelu bazy danych - którego nie mogę zmodyfikować - mam nadmiarowe kolumny, które chciałbym przechowywać w różnych klasach.

Przykład:

public class DateParams 
{ 
    public DateTime CreationDate { get; set; } 
    public DateTime ModificationDate { get; set; } 

    // some methods 
} 

public class Localization 
{ 
    public String EnglishLabel { get; set; } 
    public String FrenchLabel { get; set; } 

    // some methods 
} 

A potem chciałbym używać ich w niektóre z moich modeli:

public class Account // Localization && DateParams 
{ 
    public int ID { get; set; } 
    public String Name { get; set; } 

    public Localization Localization { get; set; } 
    public DateParams DateParams { get; set; } 
} 

public class Lead // DateParams only 
{ 
    public int ID { get; set; } 
    public String Name { get; set; } 

    public DateParams DateParams { get; set; } 
} 

Co chciałbym osiągnąć to, że coś się ten

public class LocalizationMap : EntityTypeConfiguration<Localization> 
{ 
    public LocalizationMap() 
    { 
     Property(e => e.EnglishLabel).HasColumnName("en"); 
     Property(e => e.FrenchLabel).HasColumnName("fr"); 
    } 
} 

public class AccountMap : EntityTypeConfiguration<Account> 
{ 
    public AccountMap() 
    {    
     HasKey(x => x.ID); 
     Property(e => e.Name).HasColumnName("Name"); 

     HasSubMapping(new LocalizationMap()); 
     HasSubMapping(new DateParamsMap()); 

     ToTable("Account"); 
    } 
} 

Mógłbym użyć dziedziczenia, aby rozwiązać ten problem, ale C# nie pozwala na wielokrotne dziedziczenie.

+1

Może powinieneś rzucić okiem na Entity Framework typów złożonych np tutaj: http://stackoverflow.com/questions/9931341/entity-framework-reuse-complex-type – ChriPf

+0

@ChrifP, może zamieścić swój komentarz jako asnwser, abym mógł go zaakceptować? Podszedłem do rozwiązania typu complextype. – Akli

Odpowiedz

3

Można to osiągnąć, stosując złożone typy. Są mapa do kolumn tabeli o nazwie jak complextypeName_propertyName ale takie zachowanie może być zmienione poprzez nadpisanie OnModelCreating(DbModelBuilder modelBuilder) w DbContext jak opisano w Entity Framework - Reuse Complex Type

Dla przykładu:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.ComplexType<Localization>(); 

    modelBuilder.Entity<Account>().Property(x => x.Localization.EnglishLabel).HasColumnName("en"); 
    modelBuilder.Entity<Account>().Property(x => x.Localization.FrenchLabel).HasColumnName("fr"); 
    // et cetera 
} 
2

Nie sprawię, że będziesz szczęśliwy.

Istnieje funkcja EF o nazwie Podział tabeli. Jak sama nazwa wskazuje, pozwala nam to mapować (dzielić) jedną tabelę bazy danych na wiele klas w modelu koncepcyjnym. W twoim przypadku mapowania dla Account będzie wyglądać następująco:

class AccountMap : EntityTypeConfiguration<Account> 
{ 
    public AccountMap() 
    { 
     ToTable("Account"); 
     HasKey(x => x.ID); 
     HasRequired(a => a.DateParams).WithRequiredPrincipal(); 
     HasRequired(a => a.Localization).WithRequiredPrincipal(); 
    } 
} 

class DateParamsMap : EntityTypeConfiguration<DateParams> 
{ 
    public DateParamsMap() 
    { 
     ToTable("Account"); 
    } 
} 

class LocalizationMap : EntityTypeConfiguration<Localization> 
{ 
    public LocalizationMap() 
    { 
     ToTable("Account"); 
    } 
} 

Ale to od razu pokazuje problem: nazwa tabeli „Konto” w konfiguracjach typu jest ciężko zakodowany. Nie ma możliwości ponownego użycia klas satelitarnych DateParams i Localization dla wielu typów. Przed próbą EF nie zaakceptuje generycznych, takich jak DateParams<T>.

Który jest smutny, ponieważ wszystkie inne opcje można myślę są brzydkie, niezgrabne lub w najlepszym wypadku:

  • Tworzenie podklasy DateParams i Localization (i konfiguracjach towarzyszące) dla każdego podmiotu, który ich potrzebuje.
  • Po prostu dodaj właściwości do wszystkich typów i pracuj z rzutowaniem tak bardzo, jak to tylko możliwe (ponieważ zakładam, że celem tego wysiłku jest zmniejszenie liczby właściwości, które zamierzasz przesłać).
  • Użyj jednego kontekstu obsługującego główne typy bez tych właściwości i drugiego kontekstu obsługującego typy satelitów (ponownie, aby ułatwić wyszukiwanie mniejszych właściwości). Ale niestety, możesz dołączać do instancji tylko z obu kontekstów w pamięci, tj. LINQ do obiektów.
  • Utwórz trzecią klasę satelitów, łącząc obie mniejsze klasy i użyj tych trzech klas jako typów podstawowych.
Powiązane problemy