Home > Net >  Why can't I delete the connection as I added it?
Why can't I delete the connection as I added it?

Time:08-18

I have established a many-to-many relational connection between users I created using the Identity library.

  public class AppUser:IdentityUser
{
    public AppUser()
    {
        MainUser = new List<AppUser>();
        UserConnection = new List<AppUser>();
    }
    public ICollection<AppUser> MainUser { get; set; } 
    public ICollection<AppUser> UserConnection { get; set; }
    
}

I have specified the main user in the base class as follows.

protected AppUser CurrentUser => userManager.FindByNameAsync(User.Identity.Name).Result;

I don't have a problem when I want to add links between users.

 [HttpPost]
 public IActionResult AddConnection(UserViewModel model)
{
  AppUser searchedUser = userManager.FindByNameAsync(model.UserName).Result;
  CurrentUser.UserConnection.Add(searchedUser);
  Context.SaveChanges();
  return Redirect($"FindConnection/{model.Search}");
}

But I can't delete the connection between users in the same way, why is that?

[HttpPost]
public IActionResult RemoveConnection(UserViewModel model)
{
  AppUser user = Context.Users.FirstOrDefault(x => x.UserName == model.UserName);
  CurrentUser.UserConnection.Remove(user);
  Context.SaveChanges();
  return Redirect($"FindConnection/{model.Search}");
}

enter image description here

CodePudding user response:

The behaviour for removing entities from an association will depend on whether the parent entity was loaded with those relationship references for change tracking to detect when a relationship is removed. In your case, provided that CurrentUser was loaded with the same DbContext instance:

CurrentUser = Context.Users
    .Include(x => x.UserConnection)
    .Single(x => x.UserName == currentUserName);

Then, removing an associated entity can be done simply by finding it in the CurrentUser.UserConnection and removing it, then calling SaveChanges():

[HttpPost]
public IActionResult RemoveConnection(UserViewModel model)
{
    var user = CurrentUser.UserConnection.SingleOfDefault(x => x.UserName == model.UserName);
    if (user != null)
    {
        CurrentUser.UserConnection.Remove(user);
        Context.SaveChanges();
    }
    return Redirect($"FindConnection/{model.Search}");
}

If the CurrentUser cannot be counted on to have eager-loaded its user connections then things get a bit more complicated if lazy loading is disabled. If lazy loading is enabled then accessing UserConnection should ensure that the values are loaded so the above code should work, otherwise we need to handle loading the related items.

First, we should still check to see if the user connection is there, because even if not explicitly eager loaded, the DbContext will populate relatives if any of them happen to be tracked:

    var user = CurrentUser.UserConnection.SingleOrDefault(x => x.UserName == model.UserName);
    if (user == null)
    {
        Context.Entry(CurrentUser).Collection("UserConnection").Load();
        user = CurrentUser.UserConnection.SingleOrDefault(x => x.UserName == model.UserName);
    }
    if (user != null)
    {
        CurrentUser.UserConnection.Remove(user);
        Context.SaveChanges();
    }
    return Redirect($"FindConnection/{model.Search}");
}

Essentially, check to see if a reference exists. If not, go to the DbContext to ensure that the UserConnection collection is loaded on the CurrentUser and check again. If it exists, remove it, otherwise there is nothing to do. (already removed)

  • Related