Fluent NHibernate 多对多映射,使用自动生成的 pk 而不是复合键

Posted

技术标签:

【中文标题】Fluent NHibernate 多对多映射,使用自动生成的 pk 而不是复合键【英文标题】:Fluent NHibernate Many-to-many mapping with auto-generated pk instead of composite key 【发布时间】:2010-02-02 16:50:35 【问题描述】:

我正在开发 .NET 中的 RoleProvider,使用 Fluent NHibernate 映射 Oracle 9.2 数据库中的表。

问题在于连接用户和角色的多对多表使用从序列生成的主键,而不是复合键。我无法真正改变这一点,因为我正在编写它以在更大的现有系统中实现。

这是我的用户地图:

        public UserMap()
        
            this.Table("USR");
            HasMany(x => x.Memberships).Cascade.All()
                .Table("MEMBERSHIP").Inverse().LazyLoad();
            HasManyToMany(x => x.Roles)
                .Table("USR_ROLE")
                .Cascade.SaveUpdate()
                .ParentKeyColumn("USR_ID")
                .ChildKeyColumn("ROLE_ID")
                .Not.LazyLoad();
        

还有我的角色映射:

    public RoleMap()
    
        this.Table("ROLE");            
        Map(x => x.Description).Column("ROLE_NAME");
        Map(x => x.Comment).Column("ROLE_COMMENT");
        HasManyToMany(x => x.Users)
            .Table("USR_ROLE")
            .ParentKeyColumn("ROLE_ID")
            .ChildKeyColumn("USR_ID")
            .Inverse();
    

然而,这给了我错误:

程序集“FluentNHibernate, Version=1.0.0.593, Culture=neutral, PublicKeyToken=8aa435e3cb308880”中的类型“FluentNHibernate.Cfg.FluentConfigurationException”未标记为可序列化。

是否有一个简单的修复方法允许这个 HasMayToMany 使用我的 PersistentObjectMap 扩展?我想我可能必须为这种多对多关系添加一个约定,但我不知道从哪里开始,因为我最近才开始使用 NHibernate 和 Fluent NHibernate。

我一直在研究这个问题,但似乎找不到解决方案。 任何帮助将非常感激。谢谢。

编辑:我想我在这里找到了可能的解决方案:http://marekblotny.blogspot.com/2009/02/fluent-nhbernate-and-collections.html

我将尝试为链接表创建实体和类映射的上述方法并发布我的发现。

编辑 2:我创建了上述博客文章中提到的链接实体并下载了最新的二进制文件 (1.0.0.623)。 这帮助我发现问题在于设置延迟加载并尝试在全新会话中向用户对象添加角色。

我修改了代码以将 OpenSession 移动到 HttpModule 的 BeginRequest,如 here 所述。完成此操作后,我将数据访问代码从将打开的会话包装在 using 语句中,该语句在完成时关闭会话,改为获取当前会话并仅将事务包装在 using 语句中。

这似乎已经解决了我的大部分问题,但我现在收到一条错误消息,提示“无法将集合插入”到 USR_ROLE 表中。而且我想知道上面的代码是否应该与描述为的 UserRoleMap 一起使用:

    public UserRoleMap()
    
        this.Table("USR_ROLE"); 

        /* maps audit fields id, created date/user, updated date/user */
        this.PersistentObjectMap("USR_ROLE"); 

        /* Link these tables */
        References(x => x.Role).Column("ROLE_ID");
        References(x => x.User).Column("USR_ID");
    

Hibernate 的多对多关系文档建议创建一个对象来维护一对多/多对一,就像在 ERD 中一样。我确信使用传统的命名标准会更容易,但我必须坚持使用某些缩写和奇怪的(并且并不总是正确实施)约定。

【问题讨论】:

您显然得到了可序列化异常隐藏的其他异常。获取修复不可序列化异常的最新源码,然后看看真正的异常是什么。 谢谢,詹姆斯。我今天也试试。 我添加了很多我今天发现的内容,还有一个看起来不应该是一个巨大限制的新问题。 【参考方案1】:

为了解决这个问题,我为 UserRole 创建了一个实体、映射和存储库。而且,我有一个 HasMany 映射,而不是用户和角色实体中的 HasManyToMany 映射。这有点奇怪,因为我现在有:

IList<UserRole> UserRoles get; protected set;

IList<Role> Roles get return UserRoles.Select(u => u.Role).ToList();

这行得通,但是,我不能 100% 确定为什么这行得通,而 HasManyToMany 不行。

【讨论】:

以上是关于Fluent NHibernate 多对多映射,使用自动生成的 pk 而不是复合键的主要内容,如果未能解决你的问题,请参考以下文章

Fluent NHibernate:如何在关系表上映射具有附加属性的多对多关系?

使用 Fluent NHibernate 映射或模仿多对任意关系的选项?

NHibernate 和多对多映射

流利的nhibernate映射多对多配置错误

NHibernate + Fluent NHibernate 异常

NHibernate多对多,无法删除一行