流畅的 NHibernate 多对多映射,使用自动生成的 pk 而不是复合键
我正在 .NET 中开发 RoleProvider,使用 Fluent NHibernate 映射 Oracle 9.2 数据库中的表。
问题在于连接用户和角色的多对多表使用从序列生成的主键,而不是复合键。我无法真正改变这一点,因为我编写它是为了在更大的现有系统中实现。
这是我的 UserMap:
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();
}
和我的 RoleMap:
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();
}
然而,这给了我错误:
Type 'FluentNHibernate.Cfg.FluentConfigurationException' in assembly 'FluentNHibernate, Version=1.0.0.593, Culture=neutral, PublicKeyToken=8aa435e3cb308880' 不是标记为可序列化。
是否有一个简单的修复程序可以允许此 HasMayToMany 使用我的 PersistentObjectMap 扩展?我想我可能必须为这种多对多关系添加一个约定,但我不知道从哪里开始,因为我最近才开始使用 NHibernate 和 Fluent NHibernate。
我已经研究这个问题有一段时间了,但似乎找不到解决方案。 任何帮助将不胜感激。谢谢。
编辑:我想我在这里找到了一个可能的解决方案:http://marekblotny.blogspot.com/2009/02/ Fluent-nhbernate-and-collections.html
我将尝试上述创建实体和类映射的方法链接表并发布我的发现。
编辑2:我创建了上面博客文章中提到的链接实体并下载了最新的二进制文件(1.0.0.623)。
这帮助我发现问题在于设置延迟加载并尝试在全新的会话中向用户对象添加角色。
我修改了代码,将 OpenSession 移动到 HttpModule 的 BeginRequest,如所述 此处。完成此操作后,我将数据访问代码从将打开的会话包装在 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 中一样。我确信使用传统的命名标准会容易得多,但我必须坚持使用某些缩写和奇怪的(并且并不总是正确实现的)约定。
I'm working on a RoleProvider in .NET, using Fluent NHibernate to map tables in an Oracle 9.2 database.
The problem is that the many-to-many table connecting users and roles uses a primary key generated from a sequence, as opposed to a composite key. I can't really change this, because I'm writing it to be implemented in a larger existing system.
Here is my UserMap:
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();
}
And my RoleMap:
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();
}
Yet, this is giving me the error:
Type 'FluentNHibernate.Cfg.FluentConfigurationException' in assembly 'FluentNHibernate, Version=1.0.0.593, Culture=neutral, PublicKeyToken=8aa435e3cb308880' is not marked as serializable.
Is there a simple fix to allow this HasMayToMany to use my PersistentObjectMap extension? I'm thinking I may have to add a convention for this many-to-many relationship, but I don't know where to start with that, since I've just started using NHibernate and Fluent NHibernate only recently.
I've been working on this problem for a while and I can't seem to find a solution.
Any help would be much appreciated. Thanks.
EDIT: I think I've found a possible solution here: http://marekblotny.blogspot.com/2009/02/fluent-nhbernate-and-collections.html
I'll try the above method of creating an entity and a class map for the linking table and post my findings.
EDIT 2: I created a linking entity as mentioned in the above blog post and downloaded the newest binaries (1.0.0.623).
This helped me discover that the issue was with setting lazy load and trying to add roles to the user object in a completely new session.
I modified the code to move OpenSession to the BeginRequest of an HttpModule as described here. After doing this, I changed my data access code from wrapping the open session in a using statement, which closes the session when it is finished, to getting the current session and wrapping only the transaction in a using statement.
This seems to have resolved the bulk of my issue, but I am now getting an error that says "Could not insert collection" into the USR_ROLE table. And I'm wondering if the above code should work with a UserRoleMap described as:
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's documentation for many-to-many relationship suggests creating an object to maintain a one-to-many/many-to-one, as in an ERD. I'm sure this would be much easier with conventional naming standards, but I have to stick with certain abbreviations and odd (and not always properly-implemented) conventions.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
为了解决这个问题,我为 UserRole 创建了一个实体、映射和存储库。而且,我有一个 HasMany 映射,而不是用户和角色实体中的 HasManyToMany 映射。这有点奇怪,因为我现在有:
IList;用户角色{获取; protected set;}
和
IList;角色 { get{ return UserRoles.Select(u => u.Role).ToList(); 这是可行
的,但是,我不是 100% 确定为什么它可行,而 HasManyToMany 不行。
To fix this, I created an Entity, Mapping, and Repository for UserRole. And, instead of HasManyToMany mapping in the User and Role Entities, I have a HasMany mapping. It's a little weird, because I now have:
IList<UserRole> UserRoles {get; protected set;}
and
IList<Role> Roles { get{ return UserRoles.Select(u => u.Role).ToList(); } }
This works, however, I'm not 100% sure why this works and the HasManyToMany doesn't.