Robert Sandu
Robert Sandu

Reputation: 673

Navigation Properties using two foreign keys

I have a project with several tables in the same database.

public class UserImage
{
    [Key]
    public int Id { get; set; }

    public string OwnerId { get; set; }       

    [ForeignKey("OwnerId")]
    public virtual ApplicationUser Owner { get; set; }

    //some fields are removed for brevity
}

public class FriendRequest
{
    [Key]
    public int Id { get; set; }

    public string UserId { get; set; }
    public string FutureFriendUserId { get; set; }

    [ForeignKey("UserId")]
    public virtual ApplicationUser User { get; set; }
    [ForeignKey("FutureFriendUserId")]
    public virtual ApplicationUser FutureFriendUser { get; set; }
}

public class ApplicationUser : IdentityUser
{
    //some fields are removed for brevity       
    public virtual ICollection<UserImage> UserImages { get; set; }

    public virtual ICollection<FriendRequest> FriendRequests { get; set; }

The problem is that I can find the images that belong to a user:

var userStore = new UserStore<ApplicationUser>(db);
var userManager = new UserManager<ApplicationUser>(userStore);

ApplicationUser user = userManager.FindById(User.Identity.GetUserId());

IEnumerable<string> imgs = (from image in user.UserImages select Url.Content(image.ImageUrl)).Skip(skip).Take(5).ToList();

but I can't use the same technique for the FriendRequests. If I search in the database for the rows that have UserId == User.Identity.GetUserId() or some other id, the results are what I expect. What is the problem?

Upvotes: 1

Views: 95

Answers (1)

Chris Pratt
Chris Pratt

Reputation: 239200

What you're essentially creating here is a self-referential many-to-many relationship. On your FriendRequest class, you have two properties that are foreign keys to ApplicationUser, but on your ApplicationUser class, you have only a single collection of FriendRequest. Entity Framework has no idea which foreign key should actually compose this collection. As a result, you have to make a few changes to get this working properly.

  1. You must add another navigation property. Essentially, on your ApplicationUser class you'll end up with something like the following:

    public virtual ICollection<FriendRequest> SentFriendRequests { get; set; }
    public virtual ICollection<FriendRequest> ReceivedFriendRequests { get; set; }
    

    Again, you need a collection for each foreign key.

  2. You'll need to add some fluent config to help Entity Framework determine which foreign key to use for each collection:

    public class ApplicationContext : DbContext
    {
        ...
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<FriendRequest>().HasRequired(m => m.User).WithMany(m => m.SentFriendRequests);
            modelBuilder.Entity<FriendRequest>().HasRequired(m => m.FutureFriendUser).WithMany(m => m.ReceivedFriendRequests);
        }
    

Upvotes: 1

Related Questions