prutya
prutya

Reputation: 81

Select properties for particular entities LINQ

You can probably see the result I want to get. It's easy using loop, but I can't understand how to achieve such result using LINQ extension methods

I have two contexts that target one DB. ApplicationUser is authentication class, and profileDTO profile info that I get from same DB.

ProfileDTO properties: string Id, string FirstName, string LastName

Both tables share same ID but are not connected neither through navigation properties nor any references in the DB.

IEnumerable<ViewModels.User.IndexViewModel> model;
IEnumerable<Models.ApplicationUser> users;

var profilesDtos = _profileService.GetAll();

using (var context = new Models.ApplicationDbContext())
{
    users = context.Users.ToList();
}

model = users.Select(user =>
    new ViewModels.User.IndexViewModel
    {
        Id = user.Id,
        Email = user.Email,
        PhoneNumber = user.PhoneNumber,
        LockedOutTill = user.LockoutEndDateUtc ?? default(DateTime),
        Roles = UserManager.GetRoles(user.Id)
    });

foreach (var user in model)
{
    var userProfile = profilesDtos.FirstOrDefault(o => o.Id == user.Id);
    if (userProfile != null)
    {
        user.FirstName = userProfile.FirstName;
        user.LastName = userProfile.LastName;
    }
};

I want to get all users but with Names set only in those who have profiles.

Upvotes: 1

Views: 609

Answers (3)

Vinit
Vinit

Reputation: 2607

You can use left join in Linq, like below -

IEnumerable<ViewModels.User.IndexViewModel> model;
IEnumerable<Models.ApplicationUser> users;

var profilesDtos = _profileService.GetAll();

using (var context = new Models.ApplicationDbContext())
{
    users = context.Users.ToList();
}


model = (from u in users
join p in profilesDtos on u.Id equals p.Id into tempTbl
from up in tempTbl.DefaultIfEmpty()
select new ViewModels.User.IndexViewModel
{
    Id = u.Id,
    Email = u.Email,
    PhoneNumber = u.PhoneNumber,
    LockedOutTill = u.LockoutEndDateUtc ?? default(DateTime),
    Roles = UserManager.GetRoles(u.Id),
    FirstName = up!= null? up.FirstName : string.Empty;
    LastName =  up!= null? up.LastName  : string.Empty;
}).ToList();

Upvotes: 1

AlexSam
AlexSam

Reputation: 1

As a solution, you can just join them.

MSDN

Plus DefaultIfEmpty statement.

Upvotes: 0

Anatolii Gabuza
Anatolii Gabuza

Reputation: 6260

First of all I would suggest to update your context to setup such property. If you can't do this use JOIN:

var result =
    from user in context.Users
    join profile in userProfiles on user.ID equals profile.ID 
    select new ViewModels.User.IndexViewModel {
       Id = user.Id,
       FirstName = profile.FirstName,
       ...
    }

Upvotes: 0

Related Questions