NHibernate HasMany关系。在会话重新打开之前,集合为空

时间:2011-04-19 15:28:35

标签: .net nhibernate fluent-nhibernate nhibernate-mapping one-to-many

我遇到了NHibernate的问题,正如我想的那样,懒惰负载。

我有两个相互关联的实体类:

public class User
{
    // lots of properties
    public virtual Role Role { get; set; }
}

public class Role
{
    // properties
    public virtual IList<User> UsersInRole { get;set; }
    public Role()
    {
        this.UsersInRole = new List<User>();
    }
}

关系是一对多(一个角色 - 许多用户)。 使用Fluent映射类如下:

public class UserMapping : ClassMap<Models.Accounts.User>
{
    public UserMapping() 
    {
        this.Table("Users");
        this.Id(u => u.ID).GeneratedBy.Native();
        //properties mapping            
        this.References<Models.Accounts.Role>(u => u.Role);
    }
}

public class RoleMapping : ClassMap<Models.Accounts.Role>
{
    public RoleMapping()
    {
        this.Table("Roles");
        this.Id(r => r.ID).GeneratedBy.Native();
        // properties mapping 
        this.HasMany<User>(r => r.Users).AsBag().Inverse().KeyColumn("Role_id");
    }
}

当我创建一个角色并为其分配一些用户时,Role :: Users属性为null,直到会话关闭并打开另一个。因此,请考虑以下代码:

object Foo()
{
        var session = FluentManager.OpenNewSession();
        var t1 = session.BeginTransaction();
        Role role = new Role("admin");
        session.SaveOrUpdate(role);
        t1.Commit();

        var t2 = session.BeginTransaction();
        session.SaveOrUpdate(new User() { Login = "log1", Role = role });
        t2.Commit();            

        Role oldRole = session.Get<Role>((uint)1);
        return oldRole.Users; // null here
}

另一方面,以下代码可以正常工作:

object Foo()
{
        var session = FluentManager.OpenNewSession();
        var t1 = session.BeginTransaction();
        Role role = new Role("admin");
        session.SaveOrUpdate(role);
        t1.Commit();

        var t2 = session.BeginTransaction();
        session.SaveOrUpdate(new User() { Login = "log1", Role = role });
        t2.Commit();
        session.Close();

        var session2 = FluentManager.OpenNewSession();
        Role oldRole = session2.Get<Role>((uint)1);
        return oldRole.Users; // Actual list of users
}

尽管如此,我想在一个给定的角色中处理用户集合。我做错了什么? 非常感谢提前。

PS:如果重要的话,我正在使用Fluent NHibernate 1.2和SQLite数据库。

2 个答案:

答案 0 :(得分:2)

第一个示例中role.Users为null的原因是因为您没有手动处理此关系。您需要自己维护双向关系。在您的第一个示例中,它没有从数据库中获取您的Role对象。它是从Session获得的。在您的第二个示例中,您关闭会话并打开一个新会话。这会强制它从数据库中读取信息,此时您的关系将保持不变。以下是我可以采取的措施来纠正这个问题:

public class User
{
    // lots of properties
    public virtual Role Role { get; set; }
}

public class Role
{
    // properties
    public virtual IList<User> UsersInRole { get;set; }

    public Role()
    {
        this.UsersInRole = new List<User>();
    }

    public void AddUser(User user)
    {
        if(UsersInRole.Contains(user))
            return;

        user.Role = this;
        UsersInRole.Add(user);
    }
}

您的示例现在看起来像这样:

object Foo()
{
        var session = FluentManager.OpenNewSession();
        var t1 = session.BeginTransaction();
        Role role = new Role("admin");
        session.SaveOrUpdate(role);
        t1.Commit();

        var t2 = session.BeginTransaction();
        User newUser = new User();
        newUser.Login = "log1";

        //This takes care of our relationships
        role.AddUser(newUser);

        session.SaveOrUpdate(newUser);
        t2.Commit();            

        Role oldRole = session.Get<Role>((uint)1);
        return oldRole.Users; // This should be fine here since we used AddUser
}

您还可以查看以下内容以获取更多详细信息:
Getting ManyToMany relationship to load

答案 1 :(得分:0)

黑暗中的一些镜头:

您是否尝试过访问role.Users而不是oldRole.Users

您是否尝试删除Role的构造函数?

您是否尝试使用分离的条件或QueryOver而不是Get来获取角色?也许你的角色错了。