5
votes

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.

3

3 Answers

8
votes

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.

0
votes

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".

0
votes

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.