Friday 2 September 2011

Entity Framework Code First - a Model that has Multiple Members Referring to another Single Model

Says we want to create a ‘Match’ model that will have two ‘Teams’.

The first thing that we need to do is to add two properties on the ‘Match’ class. In this example, we name them ‘HostTeamId’ and ‘GuestTeamId’ (line 9 & 12).

Then we need to add two virtual members to the class which are ‘HostTeam’ and ‘GuestTeam’ (line 15 & 18). I like to specify the ‘ForeignKey’ attribute explicitly to make it more readable even tough it may work if I omit those (not sure, I haven’t tried on this multiple references case).
public class Match
    {
        public int MatchId { get; set; }

        [Required]
        public string Name { get; set; }

        [Required]
        public int HostTeamId { get; set; }

        [Required]
        public int GuestTeamId { get; set; }

        [ForeignKey("HostTeamId")]
        public virtual Team HostTeam { get; set; }

        [ForeignKey("GuestTeamId")]
        public virtual Team GuestTeam { get; set; }

    }

Then we also need to add virtual properties on the ‘Team’ class to indicate relationship with the ‘Match’ class.
public class Team
    {
        public int TeamId { get; set; }

        [Required]
        public string Name { get; set; }

        public string City { get; set; }

        public DateTime Founded { get; set; }

        public virtual ICollection<Player> Players { get; set; }
        public virtual ICollection<Match> HomeMatches { get; set; }
        public virtual ICollection<Match> AwayMatches { get; set; }
    }

Finally we need to implement the override method ‘OnModelCreating’ on our data context class. We need to specify both two referring members of ‘Match’ class ('HostTeam' and 'GuestTeam') with correct relationship to 'Team' class. In this case I use 'WithMany' and 'HasForeignKey' methods.
. . .
        public DbSet<MvcScaffoldTest.Models.Team> Teams { get; set; }

        public DbSet<MvcScaffoldTest.Models.Match> Matches { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Match>()
                    .HasRequired(m => m.HostTeam)
                    .WithMany(t => t.HomeMatches)
                    .HasForeignKey(m => m.HostTeamId)
                    .WillCascadeOnDelete(false);

            modelBuilder.Entity<Match>()
                    .HasRequired(m => m.GuestTeam)
                    .WithMany(t => t.AwayMatches)
                    .HasForeignKey(m => m.GuestTeamId)
                    .WillCascadeOnDelete(false);
        }
        . . .

No comments: