2009-10-24 40 views
1

我已經閱讀了多個地方使用NHibernate的標識符爲 主鍵被認爲是不好的做法,因爲ID是在服務器端產生的 ,因此我們需要從服務器回覆關於生成的ID。 (我想我也看到了由Ayende後,指出MS-SQL服務器可能有問題 產生標識符,並且這可能會導致主鍵衝突)現在使用NHibernate標識符標識生成器

,比方說,我有一個非常簡單的域模型:博客和帖子。其中,每一個博客可以有 許多職位,每個職位屬於EXACTLY一個博客(一對多關係) 但我們只保存後 - >博客的關係,而不是博客 - >文章

現在假設我使用NHibernate的帶有Idenitifer ID生成這樣,我不使用級聯,所以我在我的C#代碼是這樣的:

SaveBlogInTransaction(blog1);
SavePostsInTransaction(blog1posts);


現在,我的問題是這樣的:如果插入可以在只做過一個地方我的代碼 (沒有併發問題),是否可以保證帖子與第eir博客在db中會有效嗎?


我的意思是讓我們來看看在帖子表模式:
帖子ID,PostName,PostType,BlogId

是它保證了BlogId將是有效的?

注:每個方法可以作爲一個事務,並在它提交到數據庫

回答

2

即使在重新措辭的問題中,這些帖子也會有正確的博客ID。只要調用Save,NHibernate就會在數據庫中插入Blog行,並在那時使用SCOPE_IDENTITY檢索生成的標識值。此ID值將存儲在Blog對象中,並可用於以後創建的任何帖子。

這就是爲什麼人們說基於身份的ID不是一個好選擇--NHibernate必須執行SQL來立即插入行,以便獲得正確的身份值。如果使用different identity generator,NHibernate可以避免執行SQL插入語句,直到事務被提交爲止,因爲不需要聯繫數據庫來確定對象ID的值。

+0

我同意肖恩,使用另一個生成器策略將做更有效的交易,因爲NHibernate不需要查詢數據庫來獲取插入的id。 – 2009-10-27 14:27:18

-1

這取決於你的映射結束。如果您已經映射了一對多關係,使得Blog包含BlogPosts集合,並且BlogPost具有對Blog的引用,則可以創建Blog,將Posts添加到其BlogPosts集合,並保存Blog。 NHibernate將負責插入Blog記錄,然後在保留子對象之前先設置外鍵。這保證了BlogId將是有效的。

我沒有看過NHibernate的源代碼,但我確定它使用插入後檢索身份的最佳做法,可能是SCOPE_IDENTITY。 This blog post討論了三種方法。

我不同意使用身份是一種不好的做法。它的主要問題是,在調用Flush之前,NHibernate可能會持久保留一個對象來檢索身份。因此插入可能發生在事務之外,並且記錄必須手動刪除。

+0

我不需要BlogPosts表,因爲我只保存每個帖子的 它連接到的博客。我有一個一對多的關係 在域模型,但不是在數據庫中... 我問是否保證數據庫中的帖子條目將有一個有效的blogid(並且不是NULL,如果我們沒有得到 服務器的響應以前插入的博客的ID是什麼) – 2009-10-24 18:11:31

+0

BlogId是如何生成的?我不確定我是否理解你的問題,但我認爲答案是「不」。如果您在數據庫中沒有FK關係,則無法保證有效的BlogId。 – 2009-10-24 19:20:11

+0

我有一個外鍵。我實際上使用城堡活動記錄。 在Post類中,我有一個Blog類型的屬性(但在博客類中,我沒有提及帖子...)。 現在看看我重新問我的問題的方式,當我第一次插入多個博客,然後只插入所有帖子。 可以嗎?我認爲這裏不應該使用SCOPE_IDENTITY,因爲我插入了多個博客。在與每個帖子關聯的blogid中是否有機會發現 錯誤? – 2009-10-24 20:58:56

0

我想問這個問題有點不同。 比方說,我們有這樣的代碼:


SaveBlogInTransaction(blog1);
SaveBlogInTransaction(blog2);
SavePostsInTransaction(post1_a, post1_b, ...); // all the posts of blog1
SavePostsInTransaction(post2_a, post2_b, ...); // all the posts of blog2

是保證post1_a,post1_b,...崗位blogid = blog1id?
是否保證post2_a,post2_b,... posts'blogid = blog2id?

我認爲SCOPE_IDENTITY()不適合在這裏,因爲我們先插入blog1,blog2 才把blog1_posts,並blog2_posts

注:我們有一個模型中的許多關係,但在我們分貝只爲每個帖子保存 它所屬的博客的ID(我們沒有BlogPosts表格)