2014-02-19 45 views
0

問題遇到級聯=「全部」或級聯=「保存更新」? NHibernate的一個一對多將不會更新

當我創建一個帶兒童收集瞬態的實例,一切都得到堅持。

另外,如果我更新其中一個子對象的一個​​實例,當我保存父對象時它不會更新。

我實際使用cascade="all"

Problem reproduction

的問題時,我已經加載的所有我的客戶OCCURENCES發生時,我改變了發票,但我總是使用相同的ISession

var repository = new CustomerRepository(session); 
var customers = repository.GetAll(); 
var customer = customers.Where(c => c.Name == "Stack Overflow").FirstOrDefault();   
customer.Invoices 
    .Where(i => i.Number == "1234") 
    .Approve(WindowsIdentity.GetCurrent().Name);  
repository.Save(customer); 

步步調試清楚地顯示了正在執行repository.Save()方法,和改變將不會顯示INTE底層數據庫。

可以直接對數據庫表進行更新,因此沒有限制導致數據庫端的更新失敗。

這裏有一些代碼,以防萬一它可能有所幫助。

​​

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
        namespace="MyProject.Model" 
        assembly="MyProject"> 
    <class name="Customer" table="AC_CUST" schema="AC"> 
     <id name="Id" column="AC_CUST_ID" type="Int32" unsaved-value="0"> 
     <generator class="sequence-identity"> 
      <param name="sequence">AC_CUST_ID_SEQ</param> 
      <param name="schema">AC</param> 
     </generator> 
     </id> 
     <property name="Name" column="AC_CUST_NAME" type="String" 
       not-null="true" /> 
     <property name="PhoneNumber" column="AC_CUST_PHNUM" type="Int64" 
       not-null="true" /> 
     <bag name="Invoices" table="ESO_RAPP_ACCES_INFO_DSQ" schema="AC" 
      fetch="join" lazy="true" inverse="true" cascade="all"> 
     <key column="AC_CUST_ID" foreign-key="AC_CUST_INV_FK" /> 
     <one-to-many class="Invoice" /> 
     </bag> 
    </class> 
</hibernate-mapping> 

Customer

public class Customer { 
    public Customer() { Invoices = new List<Invoice>(); } 

    public virtual int Id { get; proected set; } 
    public virtual IList<Invoice> Invoices { get; protected set; } 
    public virtual string Name { get; set; } 
    public virtual string PhoneNumber { get; set; } 
} 

Invoice.hbm.xml

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
        namespace="MyProject.Model" 
        assembly="MyProject"> 
    <class name="Invoice" table="AC_INV" schema="AC"> 
     <id name="Id" column="AC_INV_ID" type="Int32" unsaved-value="0"> 
     <generator class="sequence-identity"> 
      <param name="sequence">AC_INV_ID_SEQ</param> 
      <param name="schema">AC</param> 
     </generator> 
     </id> 
     <property name="Approved" column="AC_INV_APPRD" type="DateTime" 
       not-null="false" /> 
     <property name="Approver" column="AC_INV_APPRR" type="String" length="15" 
       not-null="false" /> 
     <property name="Number" column="AC_INV_NUMBR" type="String" length="15" 
       not-null="true" /> 
     <property name="Produced" column="AC_INV_PROD" type="DateTime" 
       not-null="false" /> 
     <many-to-one class="Customer" column="AC_CUST_ID" /> 
    </class> 
</hibernate-mapping> 

Invoice

public class Invoice { 
    public Invoice() { 
     Items = new List<Item>(); 
     Produced = DateTime.Now; 
    } 

    public virtual DateTime? Approved { get; protected set; } 
    public virtual string Approver { get; protected set; } 
    public virtual Customer Customer { get; set; } 
    public virtual int Id { get; proected set; } 
    public virtual string Number { get; set; } 
    public virtual DateTime? Produced { get; set; } 

    public virtual void Approve(string approver) { 
     Approved = DateTime.Now; 
     Approver = approver; 
    } 

    public virtual void Reject() { Produced = null; } 
} 

CustomerRepository

public class CustomerRepository { 
    public CustomerRepository(ISession session) { Session = session; } 

    public ISession Session { get; protected set; } 

    public Customer Save(Customer instance) { 
     Session.SaveOrUpdate(instance); 
     return Instance; 
    } 
} 

相關文章

讚賞任何幫助。

+0

當您構建'SessionFactory'時,您的FlushMode設置爲什麼? – Rippo

+0

'ISession.FlushMode == FlushMode.Auto'。 –

回答

0

別忘了Flush()您的環節!

NHibernate跟蹤會話生命週期中的所有變化,只應該爲表單(桌面)或頁面(Web)生存。

由於會話知道所有更改,因此它不一定會將更改提交到底層數據庫。相反,它會將所有更改記錄到字典中,然後在通過調用ISession.Flush()來刷新時,實際上要求會話承諾所做的更改。

這樣的解決方案應爲:

repository.Save(customer); 
session.Flush(); 

或者你不妨編寫你的倉庫內Commit()方法,這將在一個呼叫Flush()會話。

repository.Save(customer); 
repository.Commit(); 

而且你的倉庫看起來像:

// Assuming you stock your session in the `Session` property. 
public void Commit() { Session.Flush(); } 

這一切!