3

I am making an App which will have the Following functionality. But I am stuck at this. I have come up like this.

public class User
{
  public int Id { get; set; }
  public ICollection<User> Followers { get; set; }
  public ICollection<User> Following { get; set; }
}

And the followers table will be

public class Followers
{
public int UserId { get; set; }
public int FollowerId { get; set; }
}

But in this approach how will Entity framework will know that which are Followers and which I am following? Thanks in Advance.

Hamza Baig
  • 666
  • 1
  • 7
  • 13
  • i think it should ICollection in your class User, and you can put the RelationTypeId in followers class where RelationTypeId is referencing a look up entity RelationType( Id, Name) where Name = Follower or Following, if you want i can show you exmaple – Monah Jul 19 '15 at 09:58
  • It would be nice if you show me an example! :) – Hamza Baig Jul 19 '15 at 11:15
  • check my answer below, if you need more help ask, hope it will help you – Monah Jul 19 '15 at 11:25
  • Thanks for posting. Is this correct way to do this? I mean there will be thousands of rows with many user! – Hamza Baig Jul 19 '15 at 11:28
  • in my opinion Yes it is, if you look to the result, it obeys the normalization rules, also i added sample how to get the user followers and who the user is following – Monah Jul 19 '15 at 11:31
  • the solution i provided is called 1-to-many, you might make many-to-many solution but this will cost you more as maintaining your code and in queries, if you want i can post many-to-many solution also – Monah Jul 19 '15 at 11:34

3 Answers3

2

Looks like you want a many-to-many self-referencing relationship using code first? You don't need the Followers class. Just define the User class:

public class User
{
  public int Id { get; set; }
  public ICollection<User> Followers { get; set; }
  public ICollection<User> Following { get; set; }
}

and then write your DbContext class this way:

public class MyEntities: DbContext
{
  public DbSet<User> Users { get; set; }

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  {
    modelBuilder.Entity<User>()
        .HasMany(x => x.Followers).WithMany(x => x.Following)
        .Map(x => x.ToTable("Followers")
            .MapLeftKey("UserId")
            .MapRightKey("FollowerId"));
  }
}

A Followers table will be created in the database along with the Users table. You can test it with the following code:

using (var db = new MyEntities()) {
  var user1 = new User();
  var user2 = new User();
  var user3 = new User();
  user1.Followers = new User[] { user2 };
  user2.Followers = new User[] { user3 };
  db.Users.Add(user1);
  db.SaveChanges();
}

Update

How Entity Framework knows which are followers and which are following? The answer is, it interprets the modelBuilder statement this way:

  • Entity<User>: the subject is User;
  • HasMany(x => x.Followers): a user has many followers;
  • WithMany(x => x.Following): each follower has many following;
  • Map(...): the link table is Followers, the left key points to the subject (user), the right key points to the subject's related entity (follower).
ycsun
  • 1,825
  • 1
  • 13
  • 21
  • Thank you for your answer. But how entity framework will know that which are followers and which are following? – Hamza Baig Jul 19 '15 at 11:14
0

based on your requirements, you can do the following:

public class User
{
  public int Id { get; set; }
  public ICollection<Follower> Followers { get; set; }
  public ICollection<Follower> Following { get; set; }
}

public enum EFollowerType
{
    Follower=1,
    Following
}

public class Follower
{
  public int Id { get;  set; }
  public int UserId { get; set; }
  public int FollowedById { get; set; }
  public EFollowerType FollowerType { get; set; }

  public User User { get; set; }
  public User FollowedBy { get; set; }
}

//in the OnModelCreating function in the DbContext 

modelBuilder.Entity<Follower>()
            .HasRequired(m=> m.User)
            .WithMany(m=> m.Followers)
            .HasForeignKey(k=> k.UserId);
modelBuilder.Entity<Follower>()
            .HasRequired(m=> m.FollowedBy)
            .WithMany(m=> m.Following)
            .HasForeignKey(k=> k.FollowedById);

//to add a follower 
var user = ... user details goes here ... 
var follower = new Follower(){
   FollowerType = FollowerType.Follower, // if you want it as Follower
   User = user,
};
db.Followers.Add(follower);
db.SaveChanges();

// to know how many followers the user has

var followers = user.Followers.Count(t=>t.FollowerType ==EFollowerType.Follower);

// to know how many the user is following 
var following = user.Followers.Count(t=>t.FollowerType ==EFollowerType.Following);

you also can make FollowerType as a table if you want for example to make multilingual database or you want to add other types of Followers without modifying your code ( enum )

hope this will help you

Monah
  • 6,714
  • 6
  • 22
  • 52
0

You can Simply use :

modelBuilder.Entity<User>().HasMany(m => m.Followers).WithMany(m=>m.Following ).Map(x => x.MapLeftKey("Id").MapRightKey("FollowerId").ToTable("Followers"));
Karvan
  • 250
  • 2
  • 7