Phillip McMullen
Phillip McMullen

Reputation: 553

Entity Framework Core Unable to Determine Relationship

I have two objects: User and Relationship. A User object is created for each user of my system and multiple relationships will be created for each user depending on how many people they add as friends. The objects look as follows

public class User : IdentityUser {}

public class Relationship {
   // User who created the relationship
   public User User {get;set;}

   // User who the creation user is friends with
   public User Friend {get;set;}

   // Enum of Status (Approved, Pending, Denied, Blocked)
   public RelationshipStatus RelationshipStatus {get;set;}

   public DateTime RelationshipCreationDate {get;set;}
}

Each user could have multiple records where they match Relationship.User and they could have multiple records where they match Relationship.Friend. I have my DbContext setup as follows in the OnModelCreating method:

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<Relationship>(relationship =>
    {
        relationship.HasOne(r => r.User).WithMany(u => u.Friends);                
    });            
}

I'm new to Entity so this is probably trivial - What am I missing to have the relationship setup as I have described? Thanks!

Edit: To Be more specific, here is the error that I'm getting:

InvalidOperationException: Unable to determine the relationship represented by navigation property 'Relationship.Friend' of type 'User'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'

Edit 2: After rethinking my process, I took a different approach and used the relationships to include followers and following, rather than a collective friends list (fits my business model better anyway). I achieved this with the following:

public class User : IdentityUser {
  [InverseProperty("Friend")]
  public List<Relationship> Followers {get;set;}

  [InverseProperty("User")]
  public List<Relationship> Following {get;set;}
}

I am curious if anyone has a solution to the original problem outside of my solution, however, this works for now and seems to fit me best.

Upvotes: 3

Views: 1540

Answers (2)

TanvirArjel
TanvirArjel

Reputation: 32069

It looks like you are trying to configure many-to-many with the same entity. To do so, write your User and Relationship model classes as follows:

public class User : IdentityUser 
{
   public List<Relationship> UserFriends { get; set; }
   public List<Relationship> FriendUsers { get; set; }
}

public class Relationship {

   public string UserId {get; set;} // `UserId` type is string as you are using default identity
   public User User {get;set;}

   public string FriendId {get; set;}
   public User Friend {get;set;}

   // Enum of Status (Approved, Pending, Denied, Blocked)
   public RelationshipStatus RelationshipStatus {get;set;}

   public DateTime RelationshipCreationDate {get;set;}
}

Then in the model builder entity configuration:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
   base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<Relationship>().HasKey(r => new {r.UserId, r.FriendId});

    modelBuilder.Entity<Relationship>()
    .HasOne(r => r.User)
    .WithMany(u => u.UserFriends)
    .HasForeignKey(r => r.UserId).OnDelete(DeleteBehavior.Restrict);

    modelBuilder.Entity<Relationship>()
    .HasOne(r => r.Friend)
    .WithMany(f => f.FriendUsers)
    .HasForeignKey(r => r.FriendId).OnDelete(DeleteBehavior.Restrict);
}

Now it should work properly!

Upvotes: 0

Michael Ceber
Michael Ceber

Reputation: 2452

Have you tried adding to the User class a List of Relationships, i.e

   public class User : IdentityUser {
       List<Relationship> Relationships {get;set;}
   }

This might help EF fully understand the relationship.

Upvotes: 1

Related Questions