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

发布于 2024-11-02 07:30:24 字数 2323 浏览 1 评论 0原文

我遇到了 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 数据库,如果这很重要的话。

I've got a problem with NHibernate and, as I suppose, with lazy load.

I've got two entity classes, that are related to each other:

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>();
    }
}

Relation is One-To-Many (One role - Many users).
Classes are mapped with Fluent as following:

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");
    }
}

When I'm creating a Role, and assign some User to it - Role::Users property is null until session is closed and another one is opened. So, consider following code:

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
}

On the other hand, following code works fine:

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
}

Though, I'd like to work with collection of users in a given role w/out session close. What I did wrong?
Many thanks in advance.

PS: I'm using Fluent NHibernate 1.2 with SQLite database, if that matters.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

海的爱人是光 2024-11-09 07:30:24

第一个示例中 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
}

您还可以查看以下内容以获取更多详细信息:
获取要加载的多对多关系

The reason why role.Users is null in the first example is because you don't manually take care of this relationship. You need to maintain the bidirectional relationship yourself. In your first example it is not getting your Role object from the database. It's getting it from Session. In your 2nd example you close your session and open a new one. This forces it to read the information from the database and your relationships will be intact at this point. Here is what I might do to correct this:

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);
    }
}

Your example would now look something like this:

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
}

You can also take a look at the following for more detail:
Getting ManyToMany relationship to load

长途伴 2024-11-09 07:30:24

一些黑暗中的镜头:

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

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

您是否尝试过使用独立条件或 QueryOver 而不是 Get 来获取角色?也许你找错了角色。

Some shots in the dark:

Have you tried accessing role.Users instead of oldRole.Users?

Have you tried removing the constructor of Role?

Have you tried getting the role using a detached criteria or QueryOver rather than Get? Maybe you're getting the wrong role.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文