2014-12-11 3 views
1

В соответствии с заголовком можно написать следующий фрагмент кода в виде запроса linq. В этом текущем состоянии я обнаружил, что он не очень эффективен, занимая от 1 до 2 секунд, чтобы выполнить несколько тысяч строк.Можно ли написать это как запрос linq?

var user = this.userService.Find<ApplicationUser>(userid); 
var dict = new Dictionary<string, List<int>>(); 
List<ApplicationUser> allUsers = new List<ApplicationUser>(); 
foreach (var partner in user.Partners) 
{ 
    foreach (var programme in partner.Programmes) 
    { 
     foreach (var tm in programme.TeamMembers) 
     { 
      if (!dict.ContainsKey(tm.ApplicationUserId)) 
      { 
       dict.Add(tm.ApplicationUserId, new List<int> {partner.Id}); 
       allUsers.Add(tm.ApplicationUser); 
      } 
      else 
      { 
       dict[tm.ApplicationUserId].Add(partner.Id); 
      } 
     } 
    } 
} 
var usersviewmodel = Mapper.Map<List<UserListViewModel>>(allUsers); 
usersviewmodel.ForEach(x=> x.PartnerIds = dict[x.Id]); 

я не против того, чтобы автокарта и добавить идентификаторы позже, но было бы здорово, если бы это можно было бы сделать в запросе Linq.

+0

Я не думаю, что использование LINQ принесет какие-либо выгоды здесь (по крайней мере, в случае производительности). Если вам действительно нужно зацикливать каждый ApplicationUSerID каждого TeamMember каждого программиста, вы не можете много сделать, используя LINQ, просто приведет к сокращению кода, не более того. – HimBromBeere

+1

@HimBromBeere он использует EF, так что это не так. Преобразование итераций foreach в LINQ позволяет EF переводить запрос на язык запросов базы данных (возможно, SQL). – pseudocoder

ответ

1

Попробуйте это:

var dict = new Dictionary<string, List<int>>(); 
List<ApplicationUser> allUsers = new List<ApplicationUser>(); 
var groupedByApplicationUserId = from partner in user.Partners 
           from programme in partner.Programs 
           from tm in programme.TeamMembers 
           select new { ApplicationUserId = tm.ApplicationUserId, 
               PartnerId = partner.Id, 
               ApplicationUser = tm.ApplicationUser, 
              }; 
groupedByApplicationUserId.GroupBy(item => item.ApplicationUserId).ToList().ForEach(group => 
{ 
    dict.Add(group.Key, group.Select(item => item.PartnerId).ToList()); 
    allUsers.AddRange(group.Select(item => item.ApplicationUser)); 
}); 
2

можно устранить только один внутренний цикл:

 foreach (var partner in user.Partners) 
     { 
      foreach (var tm in partner.Programmes.SelectMany(programme => programme.TeamMembers)) { 
       if (!dict.ContainsKey(tm.ApplicationUserId)) 
       { 
        dict.Add(tm.ApplicationUserId, new List<int> { partner.Id }); 
        allUsers.Add(tm.ApplicationUser); 
       } 
       else 
       { 
        dict[tm.ApplicationUserId].Add(partner.Id); 
       } 
      } 
     } 
1

Сначала идут вниз к членам команды. Создайте пары ApplicationUserId s (как TeamMembId) и PartnerId s. Когда у вас есть эта группа, она должна быть TeamMemberId и конвертировать в словарь.

var userDict = user.Partners.SelectMany(
    p => 
     p.Programmes.SelectMany(
      prg => 
      prg.TeamMembers.Select(
       t => new { PartnerId = p.Id, TeamMembId = t.ApplicationUserId }))) 
     .GroupBy(r => r.TeamMembId) 
     .ToDictionary(g => g.Key, g => g.Select(i => i.PartnerId).ToList()); 
0

То, что вы делаете, кажется мне простым GroupBy.

var query = 
    user.Partners 
     .SelectMany(x=>x.Programmer) 
     .SelectMany(x=>x.TeamMembers) 
     .Select(x=> new { partner = partner.Id, applicationUser = tm.ApplicationUser }) 
     .GroupBy(x=>x.applicationUser) 
     .Select(x=>new { x.applicationUser, partners = x.Select(y=>y.partner) }) ; 

Но я не уверен, что EF может правильно перевести этот запрос. Особенно выбор после GroupBy.

Смежные вопросы