Mapping Friendship in dotnet (and many to many relations entity framework core)

Prashant Choudhary
2 min readApr 7, 2022

Relationships are complex. Writing code for that might be even more complex.

Here we are trying to represent friendship between two persons using dotnet.
This is the domain logic.

Now, we try to represent it with Code first migration. And this is where problem starts. But before we do anything, let us write test for storage. Following TDD helped a lot here, as trying to guess the behaviour of `ef` is super time consuming an error prone.

So here is basic `DbContext`,

public class PersonsDbContext : DbContext
{
public DbSet<Person> Persons { get; init; } = null!;

public PersonsDbContext(DbContextOptions<PersonsDbContext> dbContextOptions): base(dbContextOptions)
{
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var navigation = modelBuilder.Entity<Person>().Metadata.FindNavigation(nameof(Person.AllFriends))!;
navigation.SetPropertyAccessMode(PropertyAccessMode.Field);
navigation.SetField("_allFriends");
base.OnModelCreating(modelBuilder);
}
}

Now if you generate the migration, (and or run the test) you will notice Ef didn’t think it was many to many relationship. And we get a friendshiptable without a foreign key to Pet table. Now there are many ways to do it and most common is to use property bag. But I was adamant about not polluting my domain with unnecessary Ids.

So as a next attempt, I tried adding a foreign key, using first, HasForeignKey and then modelBuilder.Entity<Friendship>().HasMany(p => p.AllFriends).WithOne(f => f.Friend) .But when I ran tests it failed. I noticed in the DB that FriendId and PersonId was same always for some weird reason. So, it was obvious, entity framework was still not able to understand this relationship.

Then after reading couple of stackoverflow answers, I got the hint. The trick is to mimic the entity relation and build navigation from there. i.e. to Have the One to many from Person to Friendship but Skip it when doing it from Friendship to person.

Here is the final working code.

--

--