Search code examples
asp.net-mvcentity-framework-6business-logic

Remove a list of objects and add new ones efficiently using Entity Framework


I'm taking into two multiselect lists into my Edit Action Post method along with a viewmodel. For each multiselect I want to loop through each object and remove what is not selected and add what is.

In this case, I'm adding and removing users from the project that are of a certain role type. Initially I was thinking db.SaveChages() on each iteration but that seems inefficient? Any suggestions for a better approach? Currently this doesn't work... Pardon if I'm way off base, this is my 4th week learning MVC. Thanks in advance!

   // 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);
    }

Solution

  • Thought I'd swing back around and post my solution for 1 of the two role types. Same logic was applied to the other (1st solution to 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));
                            }
                       }
                    }