HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Using LINQ to group social networking links for each user

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
sociallinqnetworkingeachgroupuserlinksusingfor

Problem

I have a model named User. Each user can have some social links. Now I want to get all users with their social link as a single row in the result. Here are my models:

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection SocialLinks { get; set; }
}

public class SocialLink
{
    public string Url { get; set; }
    public SocialType Type { get; set; }
    public User User { get; set; }
    public int UserId { get; set; }
}

public enum SocialType
{
    FaceBook    = 0,
    Twitter     = 1,
    Youtube     = 2,
    Linkedin    = 3,
    GooglePlus  = 4,
    Telegram    = 5,
    Instagram   = 6
}

public class UserViewModel
{
    public string Name { get; set; }
    public string Facebook { get; set; }
    public string Twitter { get; set; }
    public string Youtube { get; set; }
    public string Linkedin { get; set; }
    public string GooglePlus { get; set; }
    public string Telegram { get; set; }
    public string Instagram { get; set; }
}


I want my query to be like this in the result:

Name    | Facebook | Twitter  | Youtube | Linkedin | GooglePlus | Telegram | Instagram
======================================================================================
Someone | facebook | @someone | youtube | linkedin | google     | @tele    | @someins


I have written following query, It works as I expected but I wonder if there's a better way for doing this:

```
users.Select(p => new UserViewModel {
Name = p.Name,
Facebook = p.SocialLinks.FirstOrDefault(x => x.Type == SocialType.FaceBook).Url ?? "#",
Twitter = p.SocialLinks.FirstOrDefault(x => x.Type == SocialType.Twitter).Url ?? "#",
Youtube = p.SocialLinks.FirstOrDefault(x => x.Type == SocialType.Youtube).Url ?? "#",
Linkedin = p.SocialLinks.FirstOrDefault(x => x.Type == SocialType.Linkedin).Url ?? "#",
Telegram = p.SocialLinks.FirstOrDefault(x => x.Type == SocialType.Tele

Solution

You could use a Dictionary and make properties of UserViewModel to address elements of this dictionary as follows:

public class UserViewModel
{
    private readonly Dictionary SocialLinks;

    public UserViewModel(User user)
    {
        SocialLinks = (user.SocialLinks ?? new SocialLink[0])
                      .ToDictionary(x => x.Type, x => x.Url);
        Name = user.Name;
    }

    private string GetUrl(SocialType socialType)
    {
        string url;
        return SocialLinks.TryGetValue(socialType, out url) && url != null ? url : "#";
    }

    public string Name { get; set; }

    public string Facebook
    {
        get { return GetUrl(SocialType.FaceBook); }
        set { SocialLinks[SocialType.FaceBook] = value; }
    }
    public string Twitter
    {
        get { return GetUrl(SocialType.Twitter); }
        set { SocialLinks[SocialType.Twitter] = value; }
    }
    public string Youtube
    {
        get { return GetUrl(SocialType.Youtube); }
        set { SocialLinks[SocialType.Youtube] = value; }
    }

    ...
}


Then your query will looks like:

users.Select(u => new UserViewModel(u)).ToList();

Code Snippets

public class UserViewModel
{
    private readonly Dictionary<SocialType, string> SocialLinks;

    public UserViewModel(User user)
    {
        SocialLinks = (user.SocialLinks ?? new SocialLink[0])
                      .ToDictionary(x => x.Type, x => x.Url);
        Name = user.Name;
    }

    private string GetUrl(SocialType socialType)
    {
        string url;
        return SocialLinks.TryGetValue(socialType, out url) && url != null ? url : "#";
    }

    public string Name { get; set; }

    public string Facebook
    {
        get { return GetUrl(SocialType.FaceBook); }
        set { SocialLinks[SocialType.FaceBook] = value; }
    }
    public string Twitter
    {
        get { return GetUrl(SocialType.Twitter); }
        set { SocialLinks[SocialType.Twitter] = value; }
    }
    public string Youtube
    {
        get { return GetUrl(SocialType.Youtube); }
        set { SocialLinks[SocialType.Youtube] = value; }
    }

    ...
}
users.Select(u => new UserViewModel(u)).ToList();

Context

StackExchange Code Review Q#151150, answer score: 6

Revisions (0)

No revisions yet.