Nhibernate'具有相同标识符值的不同对象'问题

时间:2015-10-12 10:07:54

标签: c# nhibernate fluent-nhibernate nhibernate-mapping fluent-nhibernate-mapping

我有一个更新用户实体的计划进程。此User实体与Roles对象具有ManyToMany关系。

 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实体的ICollection。

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)

所以问题是 - 为什么这个错误只会在某个点之后发生,我该怎么做才能解决它?我看过Merge在类似的这类问题上提到过 - 这会适用吗?

1 个答案:

答案 0 :(得分:0)

或许只是暗示。

我在这里看到的是:

  • 现在有角色对象(只有一些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);