Tuesday, October 18, 2016

Handling multiple Foreign Keys to the same database table in Entity Framework Code First

I recently encountered a requirement while working with Entity Framework Code First that required mapping more than 2 foreign keys to the same database table.

The convention for Entity Framework Code First, by default, does not make this easy simply by defining [ForeignKey] Data Annotations.

Fortunately, a quick search turned up this Stack Overflow thread: http://stackoverflow.com/questions/5559043/entity-framework-code-first-two-foreign-keys-from-same-table

This thread ultimately resulted in 2 possible solutions to this problem.

The first solution required the usage of the FluentAPI for Entity Framework Code First by relying on the OnModelCreating event in the DbContext class:


public class Team
{
public int TeamId { get; set;}
public string Name { get; set; }
public virtual ICollection<Match> HomeMatches { get; set; }
public virtual ICollection<Match> 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<Match>()
.HasRequired(m => m.HomeTeam)
.WithMany(t => t.HomeMatches)
.HasForeignKey(m => m.HomeTeamId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Match>()
.HasRequired(m => m.GuestTeam)
.WithMany(t => t.AwayMatches)
.HasForeignKey(m => m.GuestTeamId)
.WillCascadeOnDelete(false);
}
}

The second solution required the use of the [InverseProperty] Data Annotation instead:

public class Team
{
public int TeamId { get; set;}
public string Name { get; set; }
[InverseProperty("HomeTeam")]
public virtual ICollection<Match> HomeMatches { get; set; }
[InverseProperty("GuestTeam")]
public virtual ICollection<Match> AwayMatches { get; set; }
}
public class Match
{
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; }
}

No comments:

Post a Comment