我们有一个相当大的数据库(约 200 个表),它几乎完全使用复合主键和复合外键,使用单个“基表”,每个其他表都从该基表继承其主键的一部分:
- Parent 有单列主键 ParentId
- Child具有复合主键(ParentId,ChildId)和外键ParentId
- Nephew 有复合主键(ParentId, NephewId),外键 ParentId 和外键(ParentId, ChildId)
等等。到目前为止,我们使用自己的 ORM 框架管理整个 shebang,但我们正在考虑使用 NHibernate,我已被分配学习(我已经下载了 v2.1.2)。
映射:儿童
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Assembly" namespace="Namespace">
<class name="Child" table="Child">
<composite-id name="IdChild" class="ChildId">
<key-many-to-one name="Parent" column="ParentId" class="ParentId"></key-many-to-one>
<key-property name="Id" column="ChildId" type="Int32"></key-property>
</composite-id>
<!--simple properties-->
<set name="Nephews" table="Nephew">
<key>
<column name="ParentId"></column>
<column name="ChildId"></column>
</key>
<one-to-many class="Nephew"/>
</set>
</class>
</hibernate-mapping>
侄子
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Assembly" namespace="Namespace">
<class name="Nephew" table="Nephew">
<composite-id name="IdNephew" class="NephewId">
<key-many-to-one name="Parent" column="ParentId" class="Parent"></key-many-to-one>
<key-property name="Id" column="NephewId" type="Int32"></key-property>
</composite-id>
<many-to-one name="Child" class="Child">
<column name="ParentId"></column>
<column name="ChildId"></column>
</many-to-one>
<!--simple properties-->
</class>
如果您愿意,我也可以发布课程,为了简洁起见,我现在将省略它们(因为我将省略 Parent 的映射,因为它没有问题)。每个属性都是虚拟的,每个映射文件都是嵌入式资源,每个复合 Id 都有自己的覆盖 Equals 和 GetHashCode 的类。
问题是我无法保存 Nephew 的实例,通过一个简单的初始化new Nephew()
并传递给_session.Save()
,因为我得到一个System.IndexOutOfRangeException: Invalid index n for this SqlParameterCollection with Count=n.
.
映射中唯一重复的列是ParentId
. 删除 中的many-to-one
映射Nephew
、中的set
映射Child
和所有相关属性一切正常。
我发现了几篇报告此异常的帖子,在我的情况下最合适的似乎是这个,这让我直觉我当前的架构对于 NHibernate 是不可行的。请告诉我我错了:-)
笔记:
- 我现在没有使用 Fluent,尽管它可能是一种选择,但我更喜欢先学习基础知识;
- 是的,我们意识到复合主键是一个很大的麻烦。这个数据库多年来经过了好几手,可能不是那么熟练的人,但在重构它之前,我们将数到 10 000