2009-11-12 94 views
2

使用NHibernate,我正在尋找一種方法來在刪除持久項目時自動更新持久集合。例如: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收集即可自動更新,即從自身中刪除「帖子」。 (也許不是世界上最偉大的例子,但假設有很多博客和許多用戶,除了通過Posts之外,彼此之間沒有任何關係。要了解這是一個façade。)

在這個例子中,我只使用一個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> 
+0

您可以將博客和博客的映射文件粘貼到答案中嗎? – reach4thelasers 2009-11-12 00:53:57

回答

0

嘗試刪除級聯=所有的帖子袋。當您刷新會話時,將收藏集級聯到帖子並嘗試更新它。

您正在使用Blog.Posts.Add創建新帖子,但試圖使用PostsRepository.Delete(post)將其刪除。選擇一種策略並堅持下去。

+0

我喜歡你的建議,但韋斯做了很好的解釋,爲什麼它不是一個解決方案。他添加了一個User.FavoritePosts集合,該集合也持久存在,並且還包含對要刪除的Post的引用。只使用一個會話,我必須對引用該帖子的什麼集合進行細緻的檢查,並在我嘗試刷新會話之前將其從* all *中刪除,否則我會得到相同的ObjectDeletedException。 – Tyson 2009-11-12 21:35:23

0

我想改進這個問題多一些,說我們擴展的形勢下新Model

當我們的職務被關聯到另一個實體,除了博客,會發生什麼?即使我們只注意通過Blog.Posts.Remove刪除帖子,處理其他協會清理的一般策略是什麼?假設我們不能將所有項目都放入一個聚合根目錄,如果可以的話,我們可以通過AR將它們全部清除。所以基本上我們有聚合根源之間的聯繫,清理這些根源的最佳實踐是什麼?在這個例子中,用戶可以列出他們最喜歡的帖子,但這只是從用戶到發佈的單向關聯,沒有關聯。

我們是否需要一個域名服務,從域中刪除/刪除一個實體(不僅僅是暫時的,而是獲取它的GCed),這將刪除所有關聯?這會使NHibernate在保持更改時很高興。在這種情況下,我們不僅需要從博客中刪除帖子,而且還需要將其標記爲收藏的任何用戶刪除帖子。這是否應該生活在域名服務,應用服務中?如果發生級聯刪除,我們如何利用此服務,比如說我們刪除了一個博客,該博客的帖子被標記爲收藏夾,我們是否應該利用NHib事件並檢測帖子是否已被刪除並清理關聯?

我知道一些人建議在數據庫中使用FK級聯,但這隻有在關聯沒有加載到會話中時纔有效。如果他們被加載,他們必須被刪除。我不喜歡這種方法的是,它違背了在內存中創建真實模型的想法,即使NHib和數據庫不在那裏,它的行爲也會如此。思考?

+0

你用什麼程序來製作這些圖表? – reach4thelasers 2009-11-13 15:29:54

+0

http://yuml.me/ – Tyson 2009-11-13 19:05:29