2008-08-14 43 views
3

警告 - 我對NHibernate很新。我知道這個問題看起來很簡單 - 我確信有一個簡單的答案,但我已經在這個問題上旋轉了一段時間。我正在處理一個真正無法在結構上改變的遺留數據庫。我有一張詳細列表,列出了客戶已經接受的付款計劃。每個付款計劃都有一個ID,它鏈接回參考表以獲取計劃的條款,條件等。在我的對象模型中,我有一個AcceptedPlan類和一個Plan類。最初,我使用了從細節表返回到ref表的多對一關係來在NHibernate中建立這種關係。我還創建了一個從Plan類到AcceptedPlan類的相反方向的一對多關係。這很好,而我只是在讀數據。我可以去我的計劃對象,這是我的AcceptedPlan類的屬性來閱讀計劃的細節。當我不得不開始向細節表插入新行時,出現了我的問題。從我的閱讀中,似乎創建新的子對象的唯一方法是將其添加到父對象,然後保存會話。但我不想每次創建新的詳細記錄時都必須創建一個新的父級計劃對象。這似乎是不必要的開銷。有誰知道我是否以錯誤的方式解決這個問題?在處理遺留數據庫時,在NHibernate中建立多對一關係的最佳方法?

回答

3

我會避開擁有包含其邏輯父項的子對象,它會變得非常混亂,並非常快速地遞歸,當你這樣做。我會在你做這種事情之前看看你打算如何使用領域模型。您仍然可以在表格中輕鬆使用ID引用,並將其保留爲未映射。

這裏有兩個示例映射,可能會讓你朝着正確的方向發展,我不得不adlib表名等,但它可能會有所幫助。我可能還建議將StatusId映射到枚舉。

請注意袋子將細節表有效地映射到集合中的方式。

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping default-cascade="save-update" xmlns="urn:nhibernate-mapping-2.2"> 
    <class lazy="false" name="Namespace.Customer, Namespace" table="Customer"> 
     <id name="Id" type="Int32" unsaved-value="0"> 
      <column name="CustomerAccountId" length="4" sql-type="int" not-null="true" unique="true" index="CustomerPK"/> 
      <generator class="native" /> 
     </id> 

     <bag name="AcceptedOffers" inverse="false" lazy="false" cascade="all-delete-orphan" table="details"> 
      <key column="CustomerAccountId" foreign-key="AcceptedOfferFK"/> 
      <many-to-many 
      class="Namespace.AcceptedOffer, Namespace" 
      column="AcceptedOfferFK" 
      foreign-key="AcceptedOfferID" 
      lazy="false" 
      /> 
     </bag> 

    </class> 
</hibernate-mapping> 


<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping default-cascade="save-update" xmlns="urn:nhibernate-mapping-2.2"> 
    <class lazy="false" name="Namespace.AcceptedOffer, Namespace" table="AcceptedOffer"> 
     <id name="Id" type="Int32" unsaved-value="0"> 
      <column name="AcceptedOfferId" length="4" sql-type="int" not-null="true" unique="true" index="AcceptedOfferPK"/> 
      <generator class="native" /> 
     </id> 

     <many-to-one 
      name="Plan" 
      class="Namespace.Plan, Namespace" 
      lazy="false" 
      cascade="save-update" 
     > 
     <column name="PlanFK" length="4" sql-type="int" not-null="false"/> 
     </many-to-one> 

     <property name="StatusId" type="Int32"> 
      <column name="StatusId" length="4" sql-type="int" not-null="true"/> 
     </property> 

    </class> 
</hibernate-mapping> 
0

我會帶模型,這是如下的方法:

Customer對象包含的ICollection <PaymentPlan> PaymentPlans代表客戶所接受的方案。

客戶的PaymentPlan將使用一個包使用詳細信息表來確定哪個客戶ID映射到哪個PaymentPlans。使用cascade all-delete-orphan,如果客戶被刪除,則細節條目和客戶擁有的PaymentPlans都將被刪除。

PaymentPlan對象包含一個PlanTerms對象,它代表了付款計劃的條款。

PlanTerms將使用多對一映射級聯保存更新映射到PaymentPlan,該保存更新只會將對相關PlanTerms對象的引用插入到PaymentPlan中。

使用此模型,您可以獨立創建PlanTerms,然後當您向客戶添加新的PaymentPlan時,您需要創建一個新的PaymentPlan對象,傳入相關的PlanTerms對象,然後將其添加到相關客戶的集合中。最後,您將保存客戶並讓nhibernate級聯保存操作。

您最終將得到一個Customer對象,PaymentPlan對象和一個PlanTerms對象,其中Customer(Customer表)擁有PaymentPlans實例(詳細信息表),它們都粘附到特定的PlanTerms(計劃表)。

如果需要,我已經有了一些更具體的映射語法示例,但最好是使用您自己的模型來處理它,並且我沒有足夠的關於數據庫表的信息來提供任何具體示例。

0

我不知道這是否可能是因爲我的NHibernate體驗有限,但是您可以創建一個BaseDetail類,該類只包含Details的屬性,因爲它們直接映射到Detail表。

然後創建第二個類,該類繼承自具有其他父級計劃對象的BaseDetail類,以便您可以在創建Detail行並將PlanId分配給它時創建BaseDetail類,但是如果需要使用Parent計劃對象填充完整的Detail記錄,您可以使用繼承的Detail類。

我不知道這是否有很多意義,但讓我知道,我會進一步澄清。

0

我認爲你在這裏遇到的問題是你的AcceptedOffer對象包含一個Plan對象,然後你的Plan對象看起來包含一個包含AcceptedOffer對象的AcceptedOffers集合。與客戶同樣的事情。我認爲,物體是彼此的孩子的事實是導致你的問題的原因。

同樣,什麼使AcceptedOffer複雜是它有兩個職責:它表示包含在計劃中的提議,它表示接受客戶。這違反了單一責任原則。

您可能不得不區分計劃下的要約和客戶接受的要約。因此,我要做的事情如下:

  1. 創建一個單獨的Offer對象,該對象沒有狀態,例如,它沒有客戶並且沒有狀態 - 它只有一個OfferId和它所屬的計劃作爲它的屬性。
  2. 修改您的計劃對象以獲得一個Offers集合(它不必在其上下文中接受提議)。
  3. 最後,修改您的AcceptedOffer對象,以便它包含要約,客戶和狀態。客戶保持不變。

我認爲這將充分解決您的NHibernate映射和對象保存問題。 :)

0

可能(或可能不會)在NHibernate中有幫助的提示:您可以將對象映射到Views上,就像View是一張表一樣。只需將視圖名稱指定爲表名;只要所有的NOT NULL字段都包含在視圖中並且它的映射工作正常。

1

我寫作時沒有看到數據庫圖表。

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping default-cascade="save-update" xmlns="urn:nhibernate-mapping-2.2"> 
    <class lazy="false" name="Namespace.Customer, Namespace" table="Customer"> 
     <id name="Id" type="Int32" unsaved-value="0"> 
      <column name="customer_id" length="4" sql-type="int" not-null="true" unique="true" index="CustomerPK"/> 
      <generator class="native" /> 
     </id> 

     <bag name="AcceptedOffers" inverse="false" lazy="false" cascade="all-delete-orphan"> 
      <key column="accepted_offer_id"/> 
      <one-to-many class="Namespace.AcceptedOffer, Namespace"/> 
     </bag> 

    </class> 
</hibernate-mapping> 


<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping default-cascade="save-update" xmlns="urn:nhibernate-mapping-2.2"> 
    <class lazy="false" name="Namespace.AcceptedOffer, Namespace" table="Accepted_Offer"> 
     <id name="Id" type="Int32" unsaved-value="0"> 
      <column name="accepted_offer_id" length="4" sql-type="int" not-null="true" unique="true" /> 
      <generator class="native" /> 
     </id> 

     <many-to-one name="Plan" class="Namespace.Plan, Namespace" lazy="false" cascade="save-update"> 
      <column name="plan_id" length="4" sql-type="int" not-null="false"/> 
     </many-to-one> 

    </class> 
</hibernate-mapping> 

應該可能做的伎倆(我只做了集合的示例映射,您將不得不添加其他屬性)。

相關問題