NHibernate:多对多关系无法首先保存子对象(要么:“不能插入空值”或:“瞬态对象”)
我有一个聚合 FreightDateTime 类的寄售类。同时,FreightDateTime 类也由 GoodsItem 类聚合。以同样的方式,FreightDateTime 与我现在省略的许多其他类相关联。
为了避免数据库表 FreightDateTime 具有 ConsignmentId 外键、GoodsItemId 外键等,我决定关联应该是多对多的。这样,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>
将cascade设置为“all”会产生:
System.Data.SqlClient.SqlException: Cannot insert the value NULL into column 'DateTimeId', table 'LogiGate.dbo.FreightDateTimes'; column does not allow nulls. INSERT fails.
将cascade设置为“none”会产生:
NHibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Logistics.FreightDateTime
在这两种情况下,这意味着NHibernate正在尝试保存Consignment实例,尽管子FreightDateTime实例尚未保存。在第一种情况下,外键仍然为“null”,因此无法插入到结果表中,而在第二种情况下,NHibernate 知道实例尚未保存,因此抛出异常。
所以问题是我如何让 NHibernate 首先保存所有子实例而不明确告诉它这样做。我预感在 DateTimeId 列上允许空值可以解决问题,但我认为这既不可取也不可能。
I have a consignment class that aggregates a FreightDateTime class. At the same time, the FreightDateTime class is also aggregated by the GoodsItem class. In the same manner, FreightDateTime is associated with a number of other classes that I left out for now.
To avoid a databasetable FreightDateTime with ConsignmentId foreign key, a GoodsItemId foreign key, etc. I decided that the association should be many-to-many. This way, NHibernate would generate an association table for each relationship instead (ConsigmentFreightDateTimes, GoodsItemFreightDateTimes), which makes more sense.
So, in the mapping file, the association looks e.g. like this:
<bag name="DateTimes" table="FreightDateTimes" lazy="false" cascade="all">
<key column="ConsignmentId"/>
<many-to-many class="Logistics.FreightDateTime, Logistics" column="DateTimeId" />
</bag>
Setting cascade to "all" yields:
System.Data.SqlClient.SqlException: Cannot insert the value NULL into column 'DateTimeId', table 'LogiGate.dbo.FreightDateTimes'; column does not allow nulls. INSERT fails.
Setting cascade to "none" yields:
NHibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Logistics.FreightDateTime
In both cases, this means that NHibernate is trying to save the Consignment instance, although the child FreightDateTime instances have not been saved. In the first case, the foreign key is still 'null', which thus cannot be inserted in the resulting table, and in the second case, NHibernate is aware that the instance has not yet been saved, and thus throws the exception.
So the question is how I can get NHibernate to save all child instances first without explicitly telling it to do so. I have hunch that allowing nulls on column DateTimeId would do the trick, but I think that is neither desirable nor possible.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
尝试在另一侧也映射关联,但在该侧使用 inverse="true" 属性。因此,在 FreightDateTime 映射文件中创建一个包,以将关联与寄售映射为多对多。
另外,我在这里回答了类似的问题:在 NHibernate 中定义多对多关系以允许删除但避免重复记录的正确方法是什么
阅读问题和我的答案可能会帮助您了解发生了什么与您的多对多关联,也许会给您解决方案的提示。最后的建议是最后的手段。
上述问题的答案只是为了了解另一个人的不同问题正在经历什么。
解决方案是显式映射关联表。
如果你的表是:Person、Note 并且关联表(X表)是PersonNote
您的映射应如下所示:
如上所示,它允许您执行以下操作:
以上均通过单元测试进行测试。
您需要创建 PersonNote 类映射文件和类才能使上述工作正常进行。
如果您需要另一个类来包含注释(假设为“组织”),那么您只需将另一个关联表添加到您的架构中,称为“组织注释”,并对“组织”映射文件和“注释”映射文件执行与上面相同的操作。
我必须再次指出,对于任何想要完全控制他/她的多对多关联的人来说,这应该是最终选择。
Try to map the association on the other side also but use the inverse="true" attribute on that side. So, create in the FreightDateTime mapping file a bag to map the association as many-to-many with the Consignment.
Also, I have answered a similar question here: What is the correct way to define many-to-many relationships in NHibernate to allow deletes but avoiding duplicate records
Reading the question and my answer maybe will help you understand what is going on with your many-to-many association and maybe give you a hint for the solution. The final recommendation is kind of last resort.
The answer in the above question is just to give an idea of what is going through another person's different issue.
A solution would be to explicitly map the association table.
If your tables are: Person, Note and the association table (X table) is PersonNote
Your mappings should look like that:
As it is above it allows you the following:
All the above are tested with unit tests.
You will need to create the PersonNote class mapping file and class for the above to work.
If you need another class to have notes lets say Organisation then you only ad another association table to your schema called OrgnanisationNote and you do the same as above to the Organisation mapping file and the Note mapping file.
I must say again that this should be the final option for anyone who want to have complete control over his/hers many-to-many associations.