9.0: Adding the Follow Entity

Currently, we've added two tables to our database: Users and Photos. These have a one-to-many relationships (one user has many photos). Entity Framework is able to handle this for us with default conventions.

Here's a reminder of the diagram of our current schema:

DatabaseDiagram

We're now going to add a many-to-many relationship where many users can 'follow' many other users. We'll do this by adding a Follow entity that holds the two IDs of Users - one for the 'follower' and one for the 'followee. This is called aJoin Entity`. Here is more information in the docs.

Our Follow entity will sit between the two users and create two one-to-many relationships instead of having one many-to-many relationships.

JoinEntity

Adding the Join Entity

Inside of the .Data/Entities folder, add a new class called Follow.cs.

Again, this entity will just hold the relationship between two different Users - you can think of it as a 'following event'. When one User follows another - they are the 'follower' and the user they're following is the 'followee.' If the 'followee' follows the 'follower' back - that a new entity is created and their roles are reversed.

This can be confusing - especially the semantics of 'follower' and 'followee' but, it's important to keep straight.

public class Follow
{
    public int FollowerId { get; set; }
    public int FolloweeId { get; set; }
    public User Follower { get; set; }
    public User Followee { get; set; }
}

Adding Navigation Properties to the User

Next, we'll add two navigation properties to the User entity. One collection will hold the other Users that the entity is 'following' and one will hold the Users that 'follow' the User.

public ICollection<Follow> Follower { get; set; }

public ICollection<Follow> Followee { get; set; }

Configuring the Relationships

These relationships can be a bit tricky to wrap our head around. They're also confusing for Entity Framework! We'll need to set up configuration so that EF Core will create the relationships correctly.

Open up EFConnectContext.cs from the .Data project.

We'll add one DbSet property called Follows to store the Users the entity follows:

public DbSet<Follow> Follows { get; set; }

Next, we'll add an override for the OnModelCreating() method of the DbContext class. This is the method that is called when an entity is created.

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<Follow>()                                            //  1.
        .HasKey(k => new { k.FollowerId, k.FolloweeId });

    builder.Entity<Follow>()                                            //  2.
        .HasOne(u => u.Followee)
        .WithMany( u => u.Follower)
        .HasForeignKey(u => u.FollowerId)
        .OnDelete(DeleteBehavior.Restrict);

    builder.Entity<Follow>()                                            //  3.
        .HasOne(u => u.Follower)
        .WithMany( u => u.Followee)
        .HasForeignKey(u => u.FolloweeId)
        .OnDelete(DeleteBehavior.Restrict);
}
  1. We're telling EF Core that when a Follow entity is created - make the Primary Key by combining the FollowerId and FolloweeId.

  2. We're configuring the relationship by telling EF Core that one Followee has many Followers and the foreign key for this should be the FollowerId. We're also restricting delete behavior so that if one user is deleted - users with relationships to that user aren't also deleted.

  3. We're doing the same as in step (2), but we're defining the relationship in the other direction. We're telling EF Core that one Follower has many Followees.

Adding New Migration

Stop your .API project from running if it is currently. In your terminal, navigate to the .Data project and run a new migration:

dotnet ef migrations add FollowEntity -s "../EFConnect.API/EFConnect.API.csproj"

Next, update the database:

dotnet ef database update -s "../EFConnect.API/EFConnect.API.csproj"

Here's what our database should currently look like:

DatabaseDiagram2

Last updated