【问题标题】:Problem with NHibernate Many to Many not updating entityNHibernate 多对多不更新实体的问题
【发布时间】:2010-09-06 11:01:46
【问题描述】:

我有一个包含用户和角色的简单 NHibernate 域模型。用户和角色之间存在多对多关联。简化实体:

public class User : Entity<Guid>
{
    private IList<Role> _roles;

    public User()
    {
        _roles = new List<Role>();
    }

    public virtual UserName { get; set; }

    public virtual IList<Role> Roles { get; protected set; }
}

public class Role : Entity<Guid>
{
    private IList<User> _users;

    public Role ()
    {
        _users = new List<User>();
    }

    public virtual RoleName { get; set; }

    public virtual IList<User> Users { get; protected set; }
}

基类有一个Id属性。

映射是这样的:

public class UserMap : ClassMap<User>
{
    public UserMap()
    {
        LazyLoad();
        Id(x => x.Id)
            .GeneratedBy
            .GuidComb();

        Map(x => x.UserName)
            .Length(50)
            .Not.Nullable()
            .Unique();

        HasManyToMany(x => x.Roles)
            .Cascade.SaveUpdate();
    }
}

public class RoleMap : ClassMap<Role>
{
    public RoleMap()
    {
        LazyLoad();
        Id(x => x.Id)
            .GeneratedBy.GuidComb();

        Map(x => x.RoleName)
            .Length(20)
            .Unique()
            .Not.Nullable();

        HasManyToMany(x => x.Users)
        .Cascade.SaveUpdate()
        .Inverse();
    }
}

我让 FluentNH 创建我的 DDL,并且可以创建/更新/删除用户和角色。问题出在我对 can_add_role_to_user() 的单元测试中。简化测试如下:

public void can_add_role_to_user ()
{
    var user = members.CreateUser(username);
    var role = members.CreateRole(rolename, roledescription);

    bool result = members.AddUserToRole (username, rolename);

    // Assert
    Assert.AreEqual (true, result);
    var savedUser = members.GetUserByName(username);
    Assert.IsNotNull(savedUser);
    Assert.AreEqual (1, savedUser.Roles.Count); // Check role has been added to user
    Assert.AreEqual (user, savedUser);
    Assert.AreEqual (role, savedUser.Roles[0]);

    var savedRole = members.GetRoleByName(rolename);
    Assert.IsNotNull(newrole);
    Assert.AreEqual(1, newrole.Users.Count);    // Check user has been added to role - fails
    Assert.AreEqual (role, newrole);
    Assert.AreEqual (user, newrole.Users[0]);
}

第一组 Asserts 传递 - User 中的 IList 有一个条目。但是,角色中的 IList 具有零条目。我知道我只能从 User 实体中保存,因为我在集合地图上有 Inverse,但我希望 NH 确保集合的两侧都正确补水,否则我错过了一些东西。

【问题讨论】:

  • 我不是 FluentNH 专家,但您确定两个关系使用同一个表吗?另外,AddUserToRole 是做什么的?你什么时候冲洗?如果您使用不同的会话来检索 savedRole,会发生什么?
  • Diego,Fluent 正在使用约定来使两边的表名保持一致——在这种情况下,它是 RolesToUsers,并使 FK Role_id 和 User_id。 AddUserToRole 是我的 MembershipService 中的一个方法,它获取用户并获取角色,然后在 SaveOrUpdate 之前添加到 IList。没有明确的刷新,只是围绕一个事务。我将尝试使用不同的会话。

标签: nhibernate


【解决方案1】:

会话在哪里刷新和清除? 您是否正在清除 AddUserToRole 方法和断言之间的休眠会话?

可能是 members.GetRoleByName(rolename) 正在从身份映射中获取角色。

【讨论】:

  • AddUserToRole 方法在事务中具有 Get 和 SaveOrUpdate。在断言之前没有隐式刷新或清除会话。
  • 我稍微更改了 Asserts 并将 Assert.AreEqual (role, newRole) 和 Assert.IsSame(role, newRole) 放在 Assert(1, newRole.Users.Count()) 和 AreEqual 之前IsSame 断言通过,但 Count 没有。我认为 GetRoleByName 是从身份映射中获取的,因为它们是 AreEqual 和 IsSame。我想我需要冲洗一下。
【解决方案2】:

我已经弄清楚了双向关系发生了什么。当角色被添加到用户 NH 的角色集合中时,不会产生关系的另一端。强制 NH 进行双向的最简单方法是清除 ISession 或驱逐这两个实体(我的偏好)。这迫使 NH 访问数据库并正确构建关系的双方。即 newUser.Roles[0] 包含添加的角色,newRole.Users[0] 包含用户 - 正如我想要的那样。

我还发现我的测试工具有一个错误并且正在创建两个不同的会话:-(

【讨论】:

    猜你喜欢
    • 2011-11-01
    • 1970-01-01
    • 2015-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多