I have a scheduled process that updates a User entity. This User entity has a ManyToMany relationship with a Roles object.
public class UserMappingOverride : IAutoMappingOverride<User>
{
public void Override(AutoMapping<User> mapping)
{
mapping.HasManyToMany(u => u.Roles)
.Access.ReadOnlyPropertyThroughCamelCaseField(Prefix.None)
.AsSet()
.Cascade.SaveUpdate();
}
}
...where the Roles object is an ICollection of a UserRole entity.
UserRole
looks like this:
public class UserRole : EnumEntity<UserRole.Values>
{
public static readonly UserRole MyRole = new UserRole(Values.MyRole);
protected UserRole(){}
protected UserRole(Values value)
: base(value, value.GetDescription())
{
}
public enum Values
{
MyRole = 0
}
}
...and User (irrelevant parts omitted):
public class User : Entity
{
private readonly ICollection<UserRole> roles = new HashSet<UserRole>();
...
public virtual IEnumerable<UserRole> Roles
{
get
{
return roles.AsEnumerable();
}
}
}
As part of the scheduled process, according to some criteria, a UserRole
may be added or removed on the User. i.e.
var users = UserRepository.GetAll();
foreach (var user in users)
{
var userRole = new UserRole(0);
user.roles.Add(userRole);
var transaction = NHibernateSession.Current.BeginTransaction();
try
{
if (transaction.IsActive)
{
NHibernateSession.Current.SaveOrUpdate(user);
transaction.Commit();
}
}
catch (Exception e)
{
if (transaction.IsActive)
{
transaction.Rollback();
}
}
finally
{
NHibernateSession.Current.Close();
NHibernateSession.Current.Dispose();
}
}
When the process runs, it does so succesfully up to a point, after which every subsequent iteration of the loop results in the following:
NHibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: 0, of entity: MyProject.Core.Domain.UserRole
at NHibernate.Engine.StatefulPersistenceContext.CheckUniqueness(EntityKey key, Object obj)
So the question is - why would this error occur only after a certain point, and what can I do to resolve it? I have seen Merge mentioned on similar issues of this type - would that be applicable here?