Entity Framework Code First: due chiavi esterne dalla stessa tabella

Ho appena iniziato a utilizzare prima il codice EF, quindi sono un principiante assoluto in questo argomento.

Volevo creare relazioni tra team e partite: 1 partita = 2 squadre (casa, ospite) e risultato. Ho pensato che è facile creare tale modello, quindi ho iniziato a scrivere:

public class Team { [Key] public int TeamId { get; set;} public string Name { get; set; } public virtual ICollection Matches { get; set; } } public class Match { [Key] public int MatchId { get; set; } [ForeignKey("HomeTeam"), Column(Order = 0)] public int HomeTeamId { get; set; } [ForeignKey("GuestTeam"), Column(Order = 1)] public int GuestTeamId { get; set; } public float HomePoints { get; set; } public float GuestPoints { get; set; } public DateTime Date { get; set; } public virtual Team HomeTeam { get; set; } public virtual Team GuestTeam { get; set; } } 

E ottengo un’eccezione:

La relazione referenziale genererà un riferimento ciclico che non è consentito. [Nome vincolo = Match_GuestTeam]

Come posso creare tale modello, con 2 chiavi esterne allo stesso tavolo? TIA.

Prova questo:

 public class Team { public int TeamId { get; set;} public string Name { get; set; } public virtual ICollection HomeMatches { get; set; } public virtual ICollection AwayMatches { get; set; } } public class Match { public int MatchId { get; set; } public int HomeTeamId { get; set; } public int GuestTeamId { get; set; } public float HomePoints { get; set; } public float GuestPoints { get; set; } public DateTime Date { get; set; } public virtual Team HomeTeam { get; set; } public virtual Team GuestTeam { get; set; } } public class Context : DbContext { ... protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity() .HasRequired(m => m.HomeTeam) .WithMany(t => t.HomeMatches) .HasForeignKey(m => m.HomeTeamId) .WillCascadeOnDelete(false); modelBuilder.Entity() .HasRequired(m => m.GuestTeam) .WithMany(t => t.AwayMatches) .HasForeignKey(m => m.GuestTeamId) .WillCascadeOnDelete(false); } } 

Le chiavi primarie sono mappate per convenzione predefinita. La squadra deve avere due raccolte di partite. Non è ansible avere un’unica raccolta referenziata da due FK. La corrispondenza viene mappata senza eliminazione a cascata perché non funziona in questi riferimenti self-to-molti.

È anche ansible specificare l’attributo ForeignKey() sulla proprietà di navigazione:

 [ForeignKey("HomeTeamID")] public virtual Team HomeTeam { get; set; } [ForeignKey("GuestTeamID")] public virtual Team GuestTeam { get; set; } 

In questo modo non è necessario aggiungere alcun codice al metodo OnModelCreate

So che è un post di diversi anni e potresti risolvere il tuo problema con la soluzione di cui sopra. Tuttavia, voglio solo suggerire di usare InverseProperty per qualcuno che ha ancora bisogno. Almeno non è necessario modificare nulla in OnModelCreating.

Il codice sottostante non è testato.

 public class Team { [Key] public int TeamId { get; set;} public string Name { get; set; } [InverseProperty("HomeTeam")] public virtual ICollection HomeMatches { get; set; } [InverseProperty("GuestTeam")] public virtual ICollection GuestMatches { get; set; } } public class Match { [Key] public int MatchId { get; set; } public float HomePoints { get; set; } public float GuestPoints { get; set; } public DateTime Date { get; set; } public virtual Team HomeTeam { get; set; } public virtual Team GuestTeam { get; set; } } 

Puoi leggere ulteriori informazioni su InverseProperty su MSDN: https://msdn.microsoft.com/en-us/data/jj591583?f=255&MSPPError=-2147217396#Relationships

Puoi provare anche questo:

 public class Match { [Key] public int MatchId { get; set; } [ForeignKey("HomeTeam"), Column(Order = 0)] public int? HomeTeamId { get; set; } [ForeignKey("GuestTeam"), Column(Order = 1)] public int? GuestTeamId { get; set; } public float HomePoints { get; set; } public float GuestPoints { get; set; } public DateTime Date { get; set; } public virtual Team HomeTeam { get; set; } public virtual Team GuestTeam { get; set; } } 

Quando fai una colonna FK consenti NULLS, stai rompendo il ciclo. Oppure stiamo solo ingannando il generatore di schemi EF.

Nel mio caso, questa semplice modifica risolve il problema.

Questo perché le eliminazioni in cascata sono abilitate per impostazione predefinita. Il problema è che quando chiamate un’eliminazione sull’ quadro, cancellerà anche ciascuna delle entity framework referenziate con la chiave f. Non dovresti rendere nullable i valori “richiesti” per risolvere questo problema. Un’opzione migliore sarebbe quella di rimuovere la convenzione di eliminazione Cascade del codice EF First:

 modelBuilder.Conventions.Remove(); 

Probabilmente è più sicuro indicare esplicitamente quando eseguire una cancellazione a cascata per ciascuno dei bambini durante l’associazione / configurazione. l’ quadro.