级联= "all" 或级联= "save-update" ?NHibernate一对多不会更新



遇到的问题

当我创建一个带有子集合的临时实例时,所有内容都会被持久化。

此外,如果我更新其中一个子对象的实例,则在保存父对象时不会更新它。

我实际上在使用cascade="all"

Problem reproduction

当我加载了我的所有客户事件,并且我更改了发票,尽管我总是使用相同的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()方法,并且更改不会显示在底层数据库中。

可以直接针对数据库表进行更新,因此不会在数据库端导致更新失败

这里有一些代码,以防有帮助。

Customer.hbm.xml

<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;
}
}

相关文章

  • 停止一对多插入,但不更新
  • NHibernate-更新的代码示例

感谢您的帮助。

不要忘记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(); }

仅此而已!

相关内容

  • 没有找到相关文章

最新更新