2015-05-04 1 views
0

Я беру в себя два многосегментных списка в свой метод редактирования действия, а также с помощью viewmodel. Для каждого мультиселекта я хочу пропустить каждый объект и удалить то, что не выбрано, и добавить то, что есть.Удалите список объектов и добавьте новые эффективно с помощью Entity Framework

В этом случае я добавляю и удаляю пользователей из проекта определенного типа. Первоначально я думал о db.SaveChages() на каждой итерации, но это кажется неэффективным? Любые предложения для лучшего подхода? В настоящее время это не работает ... Простите, если я ухожу из базы, это моя 4-я неделя обучения MVC. Заранее спасибо!

// POST: Projects/Edit 
    [HttpPost] 
    [ValidateAntiForgeryToken] 
    [Authorize(Roles = "Administrator")] 
    public ActionResult Edit(ProjectEditViewModel vm, int ProjectStatusId) 
    { 
     if (ModelState.IsValid) 
     { 
      var project = db.Project.Find(vm.ProjectId); 

      project.Name = vm.ProjectName; 

      project.ProjectStatusId = ProjectStatusId; 

      var users = db.Users.Where((u => u.Projects.Any(ui => ui.ProjectId == vm.ProjectId))); 

      var currentDevs = users.Where(u => u.Roles.Any(ur => ur.RoleId == db.Roles.FirstOrDefault(r => r.Name == "Developer").Id)); 

      var currentPMs = users.Where(u => u.Roles.Any(ur => ur.RoleId == db.Roles.FirstOrDefault(r => r.Name == "Project_Manager").Id)); 

      if (currentDevs != null) 
      { 
       foreach (var cd in currentDevs) 
       { 
        project.Users.Remove(cd); 

       }     
      } 
      if (currentPMs != null) 
      { 
       foreach (var cpm in currentPMs) 
       { 
        project.Users.Remove(cpm); 

       } 
      } 

      if (vm.SelectedDevs != null) 
      { 
       foreach (var dev in vm.SelectedDevs) 
       { 
        var developer = users.FirstOrDefault(a => a.DisplayName == dev); 

        project.Users.Add(developer); 
       } 
      } 

      if (vm.SelectedPMs != null) 
      { 
       foreach (var pm in vm.SelectedPMs) 
       { 
        var projMgr = users.FirstOrDefault(a => a.DisplayName == pm); 

        project.Users.Add(projMgr); 
       } 
      } 

      db.Entry(project).State = EntityState.Modified; 

      db.SaveChanges(); 

      return RedirectToAction("Details", new { id = vm.ProjectId }); 
     } 

     return View(vm); 
    } 

ответ

1

Думал, что вернусь назад и отправлю решение для одного из двух типов ролей. Та же логика была применена к другой (1-е решение для SO woot !!!)

var devRoleId = db.Roles.FirstOrDefault(r => r.Name == "Developer").Id; 
      var users = db.Users.ToList(); 

      //currently assigned developers 
      var currentDevs = (from p in project.Users 
           where p.Roles.Any(r => r.RoleId == devRoleId) 
           select p).ToList(); 

      // if the new list is null and old list is not null, remove the old list members 
       if (vm.SelectedDevs == null) 
       { 
        if(currentDevs != null) 
        { 
         foreach (var d in currentDevs) 
         { 
          project.Users.Remove(d); 
         } 
        } 
       }     

      //if the new list is not null 
       if (vm.SelectedDevs != null) 
       { 
        if (currentDevs == null) //if the old list is null, add the new list members 
        { 
         foreach(var nd in vm.SelectedDevs) 
         { 
          project.Users.Add(users.FirstOrDefault(u => u.DisplayName == nd)); 
         } 
        } 
        else //if the old list is not null, compare each new list member to old and if its new list member is truely new, add them 
        { 
         foreach(var nd in vm.SelectedDevs) 
         { 
          if(!currentDevs.Any(cd => cd.DisplayName == nd)) 
          project.Users.Add(users.FirstOrDefault(u => u.DisplayName == nd)); 
         } 
        } 
       } 
0

Это должно сработать для вас. Вы не хотите удалять всех пользователей и повторно добавлять их каждый раз. Это вызовет массу проблем. Вместо этого вы удаляете только те, которые были отменены, а затем добавьте только те, которые были недавно выбраны (ранее не было в списке).

var devRoleId = db.Roles.FirstOrDefault(r => r.Name == "Developer").Id; 
var pmRoleId = db.Roles.FirstOrDefault(r => r.Name == "Project_Manager").Id; 

// Remove de-selected devs 
project.Users.Where(u => u.RoleId == devRoleId && !vm.SelectedDevs.Contains(u.DisplayName)) 
    .ToList().ForEach(u => project.Users.Remove(u)); 

// Add newly selected devs 
var existingDevs = project.Users.Where(u => u.RoleId == devRoleId).Select(m => m.DisplayName); 
db.Users.Where(u => vm.SelectedDevs.Exclude(existingDevs).Contains(u.DisplayName)) 
    .ToList().ForEach(u => project.Users.Add(u)); 

// Remove de-selected PMs 
project.Users.Where(u => u.RoleId == pmRoleId && !vm.SelectedPMs.Contains(u.DisplayName)) 
    .ToList().ForEach(u => project.Users.Remove(u)); 

// Add newly selected PMs 
var existingPMs = project.Users.Where(u => u.RoleId == pmRoleId).Select(m => m.DisplayName); 
db.Users.Where(u => vm.SelectedPMs.Exclude(existingPMs).Contains(u.DisplayName)) 
    .ToList().ForEach(u => project.Users.Add(u)); 
+0

Очень приятно и эффективно, спасибо! Тем не менее, VS не нравится расширения .Exclude или .RemoveAll. Я использую VS Community 2013 v4 с EF6, являются ли они частью новой версии EF? – JReam

+0

'RemoveAll' была моей ошибкой. Это будет работать только с «List », поэтому я обновил код выше, соответственно. Что касается «Исключить»? Какой тип 'vm.SelectedDevs' /' vm.SelectedPMs'? Возможно, вам придется бросить список сначала, прежде чем вызывать «Исключить», но на самом деле лучше, если вы сначала разместите выбранные элементы в качестве списка. –

+0

Я должен: project.Users.Where (u => u.Roles.Any (r => r.RoleId == devRoleId) &&! Vm.SelectedDevs.Contains (u.DisplayName)) .ToList() .ForEach (u => project.Users.Remove (u)); Поскольку пользователь может быть назначен на разные роли, это правильно? – JReam

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