public static void AddOrUpdateLink(Person follower, Person leader) { using (var db = new CloutContext()) { db.Following.AddOrUpdate(new Following { PersonId = follower.Id, FollowingId = leader.Id }); db.SaveChanges(); } }
public static IEnumerable<Person> GetFollowers(Person leader) { using (var db = new CloutContext()) { return (from follower in db.Following join person in db.Person on follower.PersonId equals person.Id where follower.FollowingId == leader.Id select person).ToList(); } }
/// <summary> /// Gets the clout of person /// This is a recursive function which traverses the tree up to it's roots /// </summary> /// <param name="leader">The current person's name for which clout is being calculated</param> /// <param name="processed"> /// A list containing the persons for which clout has been processed /// This is needed in order to escape loops in the graph /// Example: A follows B, B follows A - the recursion will continue infinitely. /// By keeping track of which nodes we already processed we avoid the loop and potential double processing /// </param> /// <returns>The number of followers for the users</returns> private static int GetClout(Person leader, ConcurrentBag<Person> processed = null) { if (processed == null) processed = new ConcurrentBag<Person>(); // Not created yet? Create it if (processed.Contains(leader)) return 0; // Already processed? break the recursion without affecting the calculation processed.Add(leader); var followers = DataAccess.GetFollowers(leader); // For each follower return the sum of 1 (for the node) and the clout of thier followers return followers.Sum(follower => 1 + GetClout(follower, processed)); }