NHibernate:自动从持久化集合中删除项目

时间:2009-11-12 00:34:06

标签: nhibernate collections

使用NHibernate,我正在寻找一种在删除持久化项目时自动更新持久化集合的方法。例如:

var post = GetNewPost();
var blog = GetCurrentBlog();
blog.Posts.Add(post);
BlogRepository.Update(blog);

User.Posts.Add(post);
UserRepository.Update(user);

----

// Somewhere else
var blog = GetCurrentBlog();
var post = blog.Posts.Last();
blog.Posts.Remove(post);

NHibSession.Flush(); // Throws an ObjectDeletedException due to 'post' 
                     // still being in the User.Posts collection

我理解在这个示例中可能存在模型和/或映射的问题,但是除了这些问题之外,我想找到一种方法来自动更新User.Posts集合,即从中删除'post'本身。 (也许不是世界上最好的例子,但假设有许多博客和许多用户,除了通过帖子之外彼此无关。了解这是一个外观。)

在这个例子中,我只使用了一个NHibernate会话。我愿意调整它,但我正在寻找一个方案,它应该对模型透明。 NHibernate事件也可以在桌面上展示,如果它可以被证明是一个好习惯。

我相信LINQ to SQL可以处理这种情况,所以我有点惊讶NHibernate不能(尽我所能的搜索能力)。是否有可用的补充框架?

以下是此示例的相关映射:

<class name="App.Core.Domain.Post, App.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Posts" xmlns="urn:nhibernate-mapping-2.2">
    <id name="Id" type="Guid" column="PostId">
        <generator class="assigned" />
    </id>
    ...
    <many-to-one cascade="save-update" access="field.pascalcase-underscore" name="Blog" column="BlogId" />

    <many-to-one cascade="save-update" access="field.pascalcase-underscore" name="User" column="UserId" />
</class>

<class name="App.Core.Domain.Blog, App.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Blogs" xmlns="urn:nhibernate-mapping-2.2">
    <id name="Id" type="Guid" column="BlogId">
        <generator class="assigned" />
    </id>
    ...
    <bag name="Posts" cascade="all" inverse="true" access="field.pascalcase-underscore">
        <key column="PostId" />
        <one-to-many class="App.Core.Domain.Post, App.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
    </bag>
</class>

<class name="App.Core.Domain.User, App.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Users" xmlns="urn:nhibernate-mapping-2.2">
    <id name="Id" type="Guid" column="UserId">
        <generator class="assigned" />
    </id>
    ...
    <bag name="Posts" cascade="all" inverse="true" access="field.pascalcase-underscore">
        <key column="PostId" />
        <one-to-many class="App.Core.Domain.Post, App.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
    </bag>
</class>

2 个答案:

答案 0 :(得分:0)

尝试删除帖子包上的cascade = all。当您刷新会话时,Post集合级联到帖子并尝试更新它。

您正在使用Blog.Posts.Add创建新帖子,但尝试使用PostsRepository.Delete(post)删除它。选择一种策略并坚持下去。

答案 1 :(得分:0)

我想更多地改进这个问题,比如我们用以下新的Model

扩展情况

当我们的帖子与Blog之外的其他实体相关联时会发生什么?即使我们注意只通过Blog.Posts.Remove删除帖子,处理其他关联清理的一般策略是什么?假设我们不能将所有项目填充到一个聚合根中,如果可以的话,我们可以通过AR清除它们。所以基本上我们在聚合根之间有联系,清理它们的最佳做法是什么?在这个例子中,用户可以列出他们最喜欢的帖子,但这只是从用户到帖子的单向关联,没有关联。

我们是否需要域服务,从域中删除/删除实体(不仅仅是让它成为瞬态但是让它获得GC),这会删​​除所有关联吗?这将使NHibernate在持续变化时感到高兴。在这种情况下,我们不仅要从博客中删除帖子,还要从任何标记为收藏的用户中删除帖子。它应该存在域服务,应用服务吗?如果发生级联删除,我们如何利用此服务,比如我们删除一个标记为收藏的帖子的博客,我们是否应该使用NHib事件并检测帖子是否被删除以及清理关联?

我知道有些人建议在数据库中使用FK级联,但这只有在关联没有加载到会话中时才有效。如果它们已加载,则必须将其删除。我不喜欢这种方法的是它违反了在内存中拥有真实模型的想法,即使NHib和数据库不存在也会如此。想法?