我有一个聚合FreightDateTime类的寄售类 . 同时,FreightDateTime类也由GoodsItem类聚合 . 以同样的方式,FreightDateTime与我现在遗漏的许多其他类相关联 .
为了避免带有ConsignmentId外键,GoodsItemId外键等的数据库表FreightDateTime,我决定该关联应该是多对多的 . 这样,NHibernate会为每个关系生成一个关联表(ConsigmentFreightDateTimes,GoodsItemFreightDateTimes),这更有意义 .
因此,在映射文件中,关联看起来例如像这样:
<bag name="DateTimes" table="FreightDateTimes" lazy="false" cascade="all">
<key column="ConsignmentId"/>
<many-to-many class="Logistics.FreightDateTime, Logistics" column="DateTimeId" />
</bag>
将级联设置为“全部”产量:
System.Data.SqlClient.SqlException: Cannot insert the value NULL into column 'DateTimeId', table 'LogiGate.dbo.FreightDateTimes'; column does not allow nulls. INSERT fails.
将级联设置为“无”会产生:
NHibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Logistics.FreightDateTime
在这两种情况下,这意味着NHibernate正在尝试保存Consignment实例,尽管尚未保存子FreightDateTime实例 . 在第一种情况下,外键仍为“null”,因此无法插入到结果表中,在第二种情况下,NHibernate知道实例尚未保存,因此抛出异常 .
所以问题是如何让NHibernate首先保存所有子实例而不明确告诉它这样做 . 我预感到允许列DateTimeId上的空值可以解决这个问题,但我认为这既不可取也不可行 .
1 回答
尝试在另一侧映射关联,但在该侧使用inverse =“true”属性 . 因此,在FreightDateTime映射文件中创建一个包,用于将关联映射为与寄售的多对多关系 .
此外,我在这里回答了类似的问题:What is the correct way to define many-to-many relationships in NHibernate to allow deletes but avoiding duplicate records
阅读问题和我的答案可能会帮助您了解您的多对多关联发生了什么,并可能会给您提供解决方案的提示 . 最终的建议是最后的选择 .
上述问题的答案只是想知道另一个人的不同问题是什么 .
解决方案是显式映射关联表 . 如果你的表是:Person,Note和关联表(X表)是PersonNote你的映射应该是这样的:
如上所述它允许您以下内容:
删除Person并仅删除关联表中的条目而不删除任何Notes
删除注释,仅删除关联表中的条目而不删除任何Person实体
通过填充Person.Notes集合并保存Person,仅从Person侧保存Cascades .
因为在Note.People中有必要使用inverse = true,所以还没有找到解决方法 .
只能通过在Note实体的PersonNotes集合中添加新项目,显式地在关联表中级联保存条目 .
以上所有都是通过单元测试进行测试的 . 您需要创建PersonNote类映射文件和类以使其工作 .
如果你需要另一个类来做笔记,那就说组织然后你只将另一个关联表添加到名为OrgnanisationNote的模式中,你就像上面那样对组织映射文件和Note映射文件做同样的事情 .
我必须再次说,这应该是任何想要完全控制他/她的多对多关联的人的最终选择 .