Nhibernate '具有相同标识符值的不同对象'问题
本文关键字:问题 对象 Nhibernate 标识符 | 更新日期: 2023-09-27 18:17:26
我有一个更新User实体的计划进程。这个User实体与Roles对象有多对多的关系。
public class UserMappingOverride : IAutoMappingOverride<User>
{
public void Override(AutoMapping<User> mapping)
{
mapping.HasManyToMany(u => u.Roles)
.Access.ReadOnlyPropertyThroughCamelCaseField(Prefix.None)
.AsSet()
.Cascade.SaveUpdate();
}
}
…其中Roles对象是UserRole实体的一个集合。
UserRole
看起来像这样:
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
}
}
…和用户(省略无关部分):
public class User : Entity
{
private readonly ICollection<UserRole> roles = new HashSet<UserRole>();
...
public virtual IEnumerable<UserRole> Roles
{
get
{
return roles.AsEnumerable();
}
}
}
作为计划过程的一部分,根据某些标准,可以在用户上添加或删除UserRole
。例如
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();
}
}
当进程运行时,它成功地运行到某一点,此后每次循环迭代都会产生以下结果:
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)
所以问题是——为什么这个错误只会在某个点之后出现,我能做些什么来解决它?我已经看到在类似的问题上提到了合并,这在这里适用吗?
也许只是一个提示。
我在这里看到的重点是:
- 现在有角色对象(只是一些
enum
) 因此没有多对多
如果这是真的,我们将有如下的对象:
public class User : Entity
{
ISet<UserRole> _roles = new HashSet<UserRole>();
public virtual ISet<UserRole> Roles
{
get { return _roles }
}
...
}
注意:我使用IList<>
来维护这样的集合,我们可以在它上面创建一个虚拟只读属性,并使这个受保护的
和集合项
public class UserRole : Entity
{
public virtual User User { get; set; }
public RoleEnum Role { get; set; }
}
可以用HasMany(一对多)
mapping.HasMany(u => u.Roles)
...
.AsSet()
.Inverse()
.Cascade.SaveUpdate();
现在就可以了,我们只需要在两端赋值
userRole.User = user;
user.Roles.Add(userRole);