1

I have a User and Following class defined as such:

public class User : IdentityUser
{
    public User()
    {
        Followers = new HashSet<Following>();
        Following = new HashSet<Following>();
    }

    [Key]
    public string ID { get; set; }
...
...

    public virtual ICollection<Following> Followers { get; set; }

    public virtual ICollection<Following> Following { get; set; } 
}

public class Following
{
        [Key]        
        public int ID {get;set;}

        [MaxLength(100)]
        public string follower { get; set; }

        [MaxLength(100)]
        public string following { get; set; }           

        public virtual User UserFollower { get; set; }

        public virtual User UserFollowing { get; set; }
 }

The properties follower and following in Following are both foreign keys for the User object and represent the relationship. Then in the DBcontext class I'm overriding the OnModelCreating:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {      
        modelBuilder.Entity<User>()
            .HasMany<Following>(u => u.Followers)
            .WithOptional()
            .HasForeignKey(c => c.following);

        modelBuilder.Entity<User>()
            .HasMany<Following>(u => u.Following)
            .WithOptional()
            .HasForeignKey(c => c.follower);
}

This works perfectly for getting a user's followers and following:

User user = await UserManager.FindByIdAsync(ID);
List<Following> followers = user.Following.ToList();

My question in basic is how do I create the UserFollower & UserFollowing relationship so that each of these properties of Following is mapped to a User?

Ideally I'd be able to do something along the lines of:

User user = await UserManager.FindByIdAsync(ID);
List<Following> followers = user.Following.ToList();

User userFollowing = followers[0].UserFollowing;

1 Answer 1

1

Modify your model a little bit

public class User : IdentityUser
{
    public User()
    {
        // Don't do this. Entity Framwork will do that for you
        // Followers = new HashSet<Following>();
        // Following = new HashSet<Following>();
    }

    // Don't add this. IdentityUser has already defined it as `Id`
    // [Key]
    // public string ID { get; set; }

    public virtual ICollection<Following> Followers { get; set; }

    public virtual ICollection<Following> Following { get; set; } 
}

public class Following
{
    [Key]        
    public int ID {get;set;}

    // [MaxLength(100)] No need to do this as this is Foreign Key Property
    public string follower { get; set; }

    // [MaxLength(100)] No need to do this as this is Foreign Key Property
    public string following { get; set; }           

    public virtual User UserFollower { get; set; }

    public virtual User UserFollowing { get; set; }
}

And then user fluent APIs to define relationship

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{      
    modelBuilder.Entity<User>()
        .HasMany(u => u.Followers)
        .WithRequired(f => f.UserFollower)
        .HasForeignKey(c => c.following);

    modelBuilder.Entity<User>()
        .HasMany(u => u.Following)
        .WithRequired(f => f.UserFollowing)
        .HasForeignKey(c => c.follower);
}

This will create a bi-directional relationship. Further EntityFramework will override all virtual properties and define behavior that you are expecting.

If you haven't modified EntityFramework configuration you will be able to do this directly

User user = await UserManager.FindByIdAsync(ID);
List<Following> followers = user.Following.ToList();

User userFollowing = followers[0].UserFollowing;
Sign up to request clarification or add additional context in comments.

1 Comment

You're correct. I definitely don't need the HashSet in the constructor I was using their own documentation but realized it wasn't necessary. Thanks a bunch, I like your Fluent API usage a lot better.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.