2013-03-27 2 views
6

Perdonami se questa domanda è stata risolta da qualche parte, ho avuto difficoltà a trovare una soluzione per questo problema.Codice quadro entità Primo rapporto molti-a-molti ed ereditarietà

Sto provando a impostare il codice EF prima su un progetto MVC4. Ho un utente e un cliente che ereditano entrambi dalla persona. Poi ho un oggetto Template che ha una relazione molti-a-molti con il cliente e una relazione uno-a-molti con l'utente. Ecco come l'ho impostato:

MODELLI

public class Person 
{ 
    [Key] 
    public int PersonID { get; set; } 

    public string LastName { get; set; } 
    public string FirstName { get; set; } 

    public string FullName 
    { 
     get 
     { 
      return String.Format("{0} {1}", FirstName, LastName); 
     } 
    } 

    public string Email { get; set; } 

    public virtual List<Template> Templates { get; set; } 
} 

public class User : Person 
{ 
    .... 
} 

public class Customer : Person 
{ 
    .... 
} 

public class Template 
{ 
    public int TemplateId { get; set; } 
    public string TemplateName { get; set; } 

    public virtual List<Customer> Customers { get; set; } 

    [ForeignKey("User")] 
    public int UserId { get; set; } 
    public virtual User User { get; set; } 
} 

CONTESTO

public class ProjectContext : DbContext 
{ 
    public ProjectContext() 
     : base("name=ProjectDB") 
    { 
    } 

    public DbSet<Template> Templates { get; set; } 
    public DbSet<User> Users { get; set; } 
    public DbSet<Customer> Customers { get; set; } 
    public DbSet<Person> People { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Conventions 
      .Remove<PluralizingTableNameConvention>(); 

     modelBuilder.Entity<Template>() 
      .HasMany(x => x.Customers) 
      .WithMany(x => x.Templates) 
      .Map(x => x.MapLeftKey("TemplateId") 
       .MapRightKey("PersonId") 
       .ToTable("TemplateCustomer") 
      ); 
    } 
} 

Se rimuovo la Persona DBSet fuori del contesto questo funziona bene, ma imposta TPT eredità. Vorrei utilizzare l'ereditarietà TPH, ma quando abilito le migrazioni con la persona DBSet nel contesto soffoca:

"Modelli" NavigationProperty non è valido. Digitare "MvcProject.Models.Customer" di FromRole "Template_Customers_Target" in AssociationType "MvcProject.Models.Template_Customers" deve corrispondere esattamente al tipo "MvcProject.Models.Person" sul quale viene dichiarata la proprietà NavigationProperty.

Dove sto andando storto qui?

risposta

14

Lei non può ereditare proprietà di navigazione da un'entità di base. Devono sempre essere dichiarato nella classe a cui si riferisce l'altra estremità della relazione.

  • Template.Customers sta riferendosi ad Customer (non Person), quindi la proprietà di navigazione inversa Templates deve essere dichiarata in Customer (non in Person)
  • Template.User sta riferendosi ad User (non Person), da qui l'inverso proprietà di navigazione Templates deve essere dichiarata in User (non in Person)

Quindi, in sostanza è necessario spostare la collezione Templates da Person in entrambe le classi derivate:

public class Person 
{ 
    // no Templates collection here 
} 

public class User : Person 
{ 
    //... 
    public virtual List<Template> Templates { get; set; } 
} 

public class Customer : Person 
{ 
    //... 
    public virtual List<Template> Templates { get; set; } 
} 

Quindi è possibile definire i due rapporti con API Fluente in questo modo:

modelBuilder.Entity<Template>() 
    .HasMany(t => t.Customers) 
    .WithMany(c => c.Templates) // = Customer.Templates 
    .Map(x => x.MapLeftKey("TemplateId") 
       .MapRightKey("PersonId") 
       .ToTable("TemplateCustomer")); 

modelBuilder.Entity<Template>() 
    .HasRequired(t => t.User) 
    .WithMany(u => u.Templates) // = User.Templates 
    .HasForeignKey(t => t.UserId); 
0

Cambia la tua selettore hasMany a People:

modelBuilder.Entity<Template>() 
     .HasMany(x => x.People) // here 
     .WithMany(x => x.Templates) 
     .Map(x => x.MapLeftKey("TemplateId") 
      .MapRightKey("PersonId") 
      .ToTable("TemplateCustomer") 
     ); 
+0

Per fare che avrei devo cambiare la mia lista di clienti in una lista di persone. Ciò vanificherebbe lo scopo, ho bisogno di un rapporto molti a molti con Template e Person. – ferics2