强制 NHibernate 在插入之前级联删除
我有一个父对象,它与子对象的 ISet
具有一对多关系。 子对象具有唯一约束(PageNum
和 ContentID
- 父对象的外键)。
<set name="Pages" inverse="true" cascade="all-delete-orphan" access="field.camelcase-underscore">
<key column="ContentId" />
<one-to-many class="DeveloperFusion.Domain.Entities.ContentPage, DeveloperFusion.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</set>
我遇到的问题是,如果我从父集合中删除 ContentPage
元素,然后在同一事务中添加具有相同唯一键的新元素...您会遇到唯一约束违规,因为NHibernate 尝试在删除之前执行插入操作。
有没有办法强制 NHibernate 首先执行删除?
I have a parent object which has a one-to-many relationship with an ISet
of child objects. The child objects have a unique constraint (PageNum
and ContentID
- the foreign key to the parent).
<set name="Pages" inverse="true" cascade="all-delete-orphan" access="field.camelcase-underscore">
<key column="ContentId" />
<one-to-many class="DeveloperFusion.Domain.Entities.ContentPage, DeveloperFusion.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</set>
The problem I've hit is if I remove a ContentPage
element from the parent collection, and then add a new one with the same unique key within the same transaction... You get a unique constraint violation because NHibernate attempts to perform the insert before the delete.
Is there a way to force NHibernate to perform the delete first?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
没有选项可以指定事务中的操作顺序,因为它是硬编码的,如下所示(来自文档):
因此,我可以挑战您回答为什么正在添加具有现有标识符的新实体? 标识符对于特定“实体”应该是唯一的。 如果该实体消失了,那么它的标识符也应该消失。
另一种选择是对该记录进行更新而不是删除/插入。 这会保持 ID 相同,因此不会违反唯一约束(至少在键上),并且您可以更改所有其他数据,使其成为“新”记录。
编辑:
显然,当我回答时,我并没有完全注意这个问题,因为这是非主键列上的唯一约束的问题。
我认为您有两种解决方案可供选择:
Session.Flush()
,这将执行到该点为止对会话的所有更改,之后您可以继续其余的操作(插入你的新对象)。 这也适用于事务内部,因此您无需担心原子性。ReplacePage
函数,该函数用新数据更新现有实体,但保持主键和唯一列相同。There is no option to specify the order of operations in a transaction as it is hard-coded as follows (from the documentation):
As such, can I challenge you to answer why you are adding a new entity with an existing identifier? An identifier is supposed to be unique to a specific "entity." If that entity is gone, so should be its identifier.
Another option would be to do an update on that record instead of a delete/insert. This keeps the ID the same so there is no unique constraint violation (on the key at least) and you can change all the other data so that it's a "new" record.
EDIT:
So apparently I wasn't entirely paying attention to the question when I responded since this is a problem with a unique constraint on a non-primary-key column.
I think you have two solutions to choose from:
Session.Flush()
after your delete which will execute all the changes to the session up to that point, after which you can continue with the rest (inserting your new object). This works inside of a transaction as well so you don't need to worry about atomicity.ReplacePage
function which updates the existing entity with new data but keeps the primary-key and the unique column the same.我遇到了同样的问题...
我有一个实体,它有一个映射到包含唯一约束的表的集合。
我不明白的是,根据 Stuarts 的回复,集合删除应该在集合插入之前发生?
当我深入研究 NHibernate 源代码时,我发现了
CollectionUpdateAction
类,该类在其Execute
方法中包含此代码:然后,我假设删除是在插入之前执行的,但是显然情况并非如此。
这个场景中没有使用CollectionUpdateAction吗? 什么时候使用 CollectionUpdateAction?
回答:
我已经解决了这个问题:
我的所有数据库访问都通过存储库进行; 在我的存储库的保存方法中,我的实体有以下代码:
因此,我保存 orderObj,并且因为级联设置为删除孤立,所以要删除的对象将从数据库中删除。
调用 SaveOrUpdate 后,我必须确保将更改刷新到数据库。
由于删除孤立级联设置可确保不会插入或更新任何 OrderLine,因此我必须循环遍历我的集合,并为每个 OrderLine 调用“SaveOrUpdate”。
这将确保插入新的订单行并更新修改的订单行。
对于未更改的订单行,不会执行任何操作。
虽然它不是理想的解决方案(恕我直言,这是一个丑陋的黑客),但它确实有效,并且它被抽象到存储库后面,所以这就是我现在处理这个问题的方式......
I am experiencing the same problem ...
I have an entity which has a collection that is mapped to a table which contains a unique constraint.
What I do not understand is, that according to Stuarts reply, collection deletions should occur before collection inserts?
When I dive into the NHibernate sourcecode, I find the
CollectionUpdateAction
class, which contains this code in itsExecute
method:Then, I would assume that deletes are executed before inserts, but apparently this is not the case.
Is the CollectionUpdateAction not used in this scenario? When is the CollectionUpdateAction used?
Answer:
I have worked around this like this:
All my database access goes via a repository; in the save method of my repository, I have this code for my entity:
So, I save the orderObj, and because the cascade is set to delete-orphan, objects that are to be deleted, will be deleted from the database.
After I call
SaveOrUpdate
, I must make sure to flush the changes to the database.Since the delete-orphan cascade setting makes sure that no OrderLines are inserted or updated, I have to loop over my collection, and call 'SaveOrUpdate' for each OrderLine.
This will make sure that new OrderLines will be inserted, and modified ones are updated.
No action will be performed for OrderLines that have not changed.
Although it is not the ideal solution (it's an ugly hack IMHO), it kind of works, and it is abstracted away behind the repository, so this is how I deal with this problem for now...
如果您摆脱子主键(ContentPage.Id)并使复合键成为主键(即PageNum和ContentID),那么我相信它可能会起作用。 这是针对休眠中发生的相同问题提供的解决方案。
If you get rid of the child primary key (ContentPage.Id) and make the composite key the primary key (ie PageNum and ContentID), then I believe it may work. This is a solution offered to the same issue occurring in hibernate.