Ho il seguente modello di supertipo / sottotipo a livello di database:
MotherTable
- MainDiscriminator
- CommonAttribute1
- CommonAttribute2
ChildTable1
- MainDiscriminator (value: 1)
- AdditionalAttributes...
ChildTable2
- MainDiscriminator (value: 2)
- AdditionalAttributes...
Fino a questo punto, configurazione di implementazione piuttosto tipica per la mappatura:
Map<ChildTable1>(m => m.Requires("MainDiscriminator").HasValue("1"));
Map<ChildTable2>(m => m.Requires("MainDiscriminator").HasValue("2"));
Ora dove sto avendo problemi è la configurazione del secondo livello di ereditarietà; ChildTable2 ha figli grandi con un discriminatore diverso di cui MotherTable non sa nulla. Sarebbe come questo
ChildTable2
- MainDiscriminator (value: 2)
- AdditionalAttributes...
- SecondaryDiscriminator
GrandChild1
- SecondaryDiscriminator (value: 1)
- AdditionalAttributes...
GrandChild2
- SecondaryDiscriminator (value: 2)
- AdditionalAttributes...
Ho provato vari approcci, ma ho riscontrato errori di configurazione che indicano che due entità vengono mappate sulla stessa riga o che EF tenta di immettere un valore nullo in una colonna non esistente denominata "Discriminator" in MotherTable.
Uno dei viali che sembrava consentire di aggirare questo problema, era un DbInterceptor che rimuoveva quegli indesiderati inserimenti / aggiornamenti / cancellazioni di colonne "Discriminator", ma preferirei non andarci.
Qualsiasi idea / pensiero sarebbe apprezzata.
Nel momento in cui ho scritto questo, potresti aver già trovato la soluzione. Tuttavia, l'ho fatto in modo da poter avere un'idea di quali altre opzioni potrebbero avere nel tavolo.
Posso dire che il tuo caso è quello giusto per implementare l'ereditarietà di TpT (Table per Type) in EF 6.
Quindi, questa è la mia opinione sul caso, partendo da semplici classi POCO:
public class MotherTable
{
public int MotherId { get; set; }
public int MainDiscriminator { get; set; }
public string CommonAttribute1 { get; set; }
public string CommonAttribute2 { get; set; }
}
public class ChildTable1 : MotherTable
{
public string AdditionalAttribute1 { get; set; }
}
public class ChildTable2 : MotherTable
{
public int SecondaryDiscriminator { get; set; }
public string AdditionalAttribute2 { get; set; }
}
public class GrandChild1 : ChildTable2
{
public string AdditionalAttributes21 { get; set; }
}
public class GrandChild2 : ChildTable2
{
public string AdditionalAttributes22 { get; set; }
}
Setup in EF 6 utilizzando l'API fluente (scenario code-first) come questo:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MotherTable>().ToTable("MotherTable").HasKey<int>(c => c.MotherId);
modelBuilder.Entity<ChildTable1>().ToTable("ChildTable1");
modelBuilder.Entity<ChildTable2>().ToTable("ChildTable2");
modelBuilder.Entity<GrandChild1>().ToTable("GrandChild1");
modelBuilder.Entity<GrandChild2>().ToTable("GrandChild2");
}
Testato eseguendo questo snippet:
using (var context = new StackoverflowEntities())
{
var account1 = new GrandChild1
{
MotherId = 1,
MainDiscriminator = 2,
CommonAttribute1 = "Mother common 1",
CommonAttribute2 = "Mother common 2",
AdditionalAttribute2 = "Child Add Attr 2",
AdditionalAttributes21 = "Grand Child Add Attr 2.1",
SecondaryDiscriminator = 1
};
var accounts1 = context.Set<GrandChild1>();
accounts1.Add(account1);
var account2 = new GrandChild2
{
MotherId = 2,
MainDiscriminator = 2,
CommonAttribute1 = "Mother common 1",
CommonAttribute2 = "Mother common 2",
AdditionalAttribute2 = "Child Add Attr 2",
AdditionalAttributes22 = "Grand Child Add Attr 2.2",
SecondaryDiscriminator = 2
};
var accounts2 = context.Set<GrandChild2>();
accounts2.Add(account2);
context.SaveChanges();
}
Genererà uno schema di database come questo:
e distribuirà i dati inseriti (dallo snippet qui sopra), in questo modo:
Spero che questo post possa darti qualcosa da considerare, anche se hai corretto i tuoi codici e non è esattamente quello che stai cercando. O forse potresti dirmi qualcosa che non so, se esiste.