5

Ho 3 classi nel mio modello, come potete vedere di seguito.Definizione della relazione molti a molti nel primo schema di entità del codice

[Table("UserProfile")] 
public class UserProfile 
{ 
    [Key] 
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 

    public string UserName { get; set; } 

    public ICollection<MartialArtUserProfile> MartialArtUserProfiles { get; set; } 
} 

[Table("MartialArt")] 
public class MartialArt 
{ 
    [Key] 
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 

    public string Name { get; set; } 

    public string Description { get; set; } 

    public string IconPath { get; set; } 

    public string ImagePath { get; set; } 

    public ICollection<MartialArtUserProfile> MartialArtUserProfiles { get; set; } 
} 

public class MartialArtUserProfile 
{ 
    public int UserProfileId { get; set; } 
    public UserProfile UserProfile { get; set; } 

    public int MartialArtId { get; set; } 
    public MartialArt MartialArt { get; set; } 
} 

E ho una classe di configurazione per la relazione molti a molti, come di seguito:

public class MartialArtUserProfileConfiguration : EntityTypeConfiguration<MartialArtUserProfile> 
{ 
    public MartialArtUserProfileConfiguration() 
    { 
     HasKey(a => new { a.MartialArtId, a.UserProfileId }); 

     HasRequired(a => a.MartialArt) 
      .WithMany(s => s.MartialArtUserProfiles) 
      .HasForeignKey(a => a.MartialArtId) 
      .WillCascadeOnDelete(false); 

     HasRequired(a => a.UserProfile) 
      .WithMany(p => p.MartialArtUserProfiles) 
      .HasForeignKey(a => a.UserProfileId) 
      .WillCascadeOnDelete(false); 
    } 
} 

Dopo aver definito i miei soggetti una relazione quando si tenta di eseguire Update-Database in Package Manager Console , dice:

Uno o più errori di convalida sono stati rilevati durante la generazione del modello:

\ tSystem.Data.Entity.Edm.EdmEntityType:: EntityType 'MartialArtUserProfile' non ha alcuna chiave definita. Definire la chiave per questo EntityType. \ tSystem.Data.Entity.Edm.EdmEntitySet: EntityType: EntitySet 'MartialArtUserProfiles' è basato sul tipo 'MartialArtUserProfile' che non ha chiavi definite.

Cosa sto sbagliando?

Grazie in anticipo,

+0

hai davvero bisogno della classe MartialArtUserProfile o la stai solo usando per creare una relazione molti-a-molti? –

+0

Lo sto usando solo per creare una relazione molti-a-molti. @Sniffer – anilca

risposta

8

Se ho ben capito si sta semplicemente cercando di creare una relazione molti a molti con un tavolo transitiva. Se è così, questo è un altro modo per avvicinarsi a questo. Usa Fluent API per mappare come sotto. È possibile modificare UserProfileToMartialArt in qualsiasi modo si desideri che il nome della tabella sia. Invece di creare il modello MartialArtUserProfile consenti a EF di creare una via di mezzo per te. Questo specifica anche le tue chiavi che dovrebbero aiutarti a risolvere l'errore.

modelBuilder.Entity<UserProfile>() 
    .HasMany(b => b.MartialArts) 
    .WithMany(a => a.UserProfiles) 
    .Map(m => m.MapLeftKey("MartialArtId") 
     .MapRightKey("UserProfileId") 
     .ToTable("UserProfileToMartialArt")); 

In MartialArts modello messo

public IList<UserProfile> UserProfiles { get; set; } 

In ProfiloUtente modello messo

public IList<MartialArt> MartialArts { get; set; } 
+1

Ho ricevuto feedback di recensione, che usando .Map in fluente per definire la relazione sopra, non era la migliore pratica, in quanto la soluzione poteva essere compilata dopo una modifica, e non sarebbe fino a runtime che questo è evidente. Suggeriresti di usare Reflection, o qualche altro mezzo (in cima alla mia testa, assegnando l'attributo della tabella delle entità e la mappatura a costante?) –

6

provare a farlo in questo modo:

[Table("UserProfile")] 
public class UserProfile 
{ 
    [Key] 
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 

    public string UserName { get; set; } 

    [InverseProperty("UserProfiles")] 
    public IList<MartialArt> MartialArts { get; set; } 
} 

[Table("MartialArt")] 
public class MartialArt 
{ 
    [Key] 
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 

    public string Name { get; set; } 

    public string Description { get; set; } 

    public string IconPath { get; set; } 

    public string ImagePath { get; set; } 

    [InverseProperty("MartialArts")] 
    public IList<UserProfile> UserProfiles { get; set; } 
} 
+0

Questo funziona bene per me. Sebbene io sia in uno scenario in cui mi interessa che * solo * un'entità sia collegata all'altra. È possibile usare questo? All'inizio avevo appena un IList Others {get; set;} ma non funzionava correttamente – Mzn

+0

Stai parlando della relazione 1 a 1? –

+0

Sto parlando di una (molti-molti) rapporto molti-molti ... per senso unico intendo nel mio codice che voglio una proprietà di navigazione. Questo non è un grosso problema, mi chiedo solo come, se possibile, – Mzn

5

In EntityFramework 6.1, non è necessario fare nulla di tutto questo - è sufficiente aggiungere le collezioni dei due tipi per ogni classe e tutto cade al suo posto.

public class UserProfile { 
    public int Id { get; set; } 
    public string UserName { get; set; } 
    public virtual ICollection<MartialArt> MartialArts { get; set; } 

    public UserProfile() { 
     MartialArts = new List<MartialArt>(); 
    } 
} 

public class MartialArt { 
    public int Id { get; set; } 
    public string Name { get; set; } 
    // *snip* 
    public virtual ICollection<UserProfile> UserProfiles { get; set; } 

    public MartialArt() { 
     UserProfiles = new List<UserProfile>(); 
    } 
} 
+0

Impressionante, ha funzionato per me. Questo è come dovrebbe essere. Vai 6.1 – parliament

+0

Se questa è una evoluzione della risposta di Admir sopra (http://stackoverflow.com/a/15328042/489396) e la "caduta in posizione" si basa sulla convenzione, quali convenzioni sono richieste tra la tabella della mappa? –

+1

@GusCrawford - La tabella di mappatura viene tenuta completamente nascosta dal codice, verrà creata semplicemente avendo due raccolte dell'oggetto opposto nel codice. –