我们有一个相当大的数据库(~200个表)几乎完全使用复合主键和复合外键,使用单个“基表”,其他每个表继承其主键的一部分:
等等。到目前为止,我们使用自己的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>
Nephew公司
<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>
如果你愿意,我也可以发布课程,为了简洁我现在省略它们(因为我省略了父的映射,因为它没有问题)。每个属性都是虚拟的,每个映射文件都是一个嵌入式资源,每个复合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
映射以及所有相关属性一切正常。
我发现有几个帖子报告了这个异常,在我的情况下最合适的似乎是this one,这让我觉得我的当前的架构在NHibernate中是不可行的。请告诉我我错了: - )
注意:
答案 0 :(得分:0)
不幸的是,您将无法以当前形式映射该关系,如您所推断的那样。
然而,有一个解决方法。不要将Nephew.Child
映射为多对一,而是将ChildId
映射为常规属性,并在需要检索子项时使用查询。
还有一次机会。当且仅当Nephew.Child不为null且不可变时,您可以映射引用Child而不是父项的键:
<class name="Nephew" table="Nephew">
<composite-id name="IdNephew" class="NephewId">
<key-many-to-one name="Child">
<column="ParentId">
<column="ChildId">
</key-many-to-one>
<key-property name="Id" column="NephewId"/>
</composite-id>
</class>
答案 1 :(得分:0)
我找到了更好的解决方案:
<many-to-one name="Child" class="Child">
<formula>ParentId</formula>
<column name="ChildId"></column>
</many-to-one>
我已经尝试了它并且它给了我一个错误,但后来我注意到this patch,所以我下载了3.0.0 alpha2并且一切正常!多亏了这个解决方案,我可以按原样映射Nephew.Child
属性。
我仍然需要Child.Add(Nephew)
方法(但我意识到即使在文档中也建议这样做)