NHibernate - how to delete an item from many-to-many relationship?
Asked Answered
O

3

5

I've following mapping for two tables having a Many-to-Many relationship between them. How do I delete an entry from the mapping table, which is 'ProjectUser' in my case?

public ProjectMap()
{
    Id(x => x.Id);
    Map(x => x.ProjectName);
    Map(x => x.Description);
    References<User>(x => x.Owner);
    HasManyToMany(x => x.Users)
        .Cascade.SaveUpdate()
        .Table("ProjectUser")
        .Not.LazyLoad();
}


public UserMap()
{
    Id(x => x.Id);
    Map(x => x.FirstName);
    Map(x => x.LastName);
    Map(x => x.UserName);
    HasManyToMany(x => x.Projects)
        .Cascade.SaveUpdate()
        .Inverse()
        .Table("ProjectUser")
        .Not.LazyLoad();
}

EDIT: changed Cascade to SaveUpdate as suggested in answers. Here is the code I use to commit data to SQLite database.

using (var trans = session.BeginTransaction())
{
    var existingUsers = project.Users.ToList();
    foreach (var item in existingUsers)
    {
        if (selectedUsers.Count(x => x.Id == item.Id) == 0)
            project.Users.RemoveAt(project.Users.IndexOf(item));
    }
    session.SaveOrUpdate(project); // This fixed the issue
    session.Flush();
    foreach (var item in selectedUsers)
    {
        if (project.Users.Count(x => x.Id == item.Id) == 0)
        {
            project.AddUser(session.Get<User>(item.Id));
        }
    }
    session.SaveOrUpdate(project);
    session.Flush();
    trans.Commit();
}

// Add user code in Project class
public virtual void AddUser(User userToAdd)
{
    if (this.Users == null)
        this.Users = new List<User>();
    userToAdd.Projects.Add(this);
    this.Users.Add(userToAdd);
}

Whenever I try to save/update I'm getting the following error:

a different object with the same identifier value was already associated with the session: 10, of entity: Models.Project

EDIT2: Should use session.SaveOrUpdate(project) and session.Flush() to avoid error stated above.

Oteliaotero answered 16/2, 2012 at 17:50 Comment(0)
O
8

If you only want to remove the ProjectUser entry and not actually delete the entity on the other side you need to change from Cascade.All() to Cascade.SaveUpdate().

Currently if you removed a user from a project and saved the project it would delete the ProjectUser entry and the User object.

Otisotitis answered 16/2, 2012 at 18:56 Comment(1)
This fixed the issue, all I have to do extra was save and flush before I remove and add another projectUser.Oteliaotero
G
0

My guess would be to remove the appropriate User entity from the Project.Users collection and save that project. The cascade would then remove the entry in "ProjectUser".

Gelderland answered 16/2, 2012 at 18:24 Comment(0)
P
0

If you want to remove link between a Project and an User (it means removing record from the join table ProjectUser) you should act from noniverse side. In your case it means you should remove user entity from the Project's Users collection:

project.Users.Remove(user);

In my opinion cascade in many-to-many assoc. should be set to SaveUpdate. You don't want to delete the project when the user is deleted.

Pfaff answered 16/2, 2012 at 18:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.