使用NHibernate保存子集合

时间:2010-04-14 12:23:54

标签: nhibernate nhibernate-mapping

我正在学习NHibernate,所以请耐心等待。

我有一个Order类和一个Transaction类。订单与交易有一对多的关联。我的数据库中的事务表对OrderId外键具有非空约束。

订单类:

    public class Order {
    public virtual Guid Id { get; set; }
    public virtual DateTime CreatedOn { get; set; }
    public virtual decimal Total { get; set; }

    public virtual ICollection<Transaction> Transactions { get; set; }

    public Order() {
        Transactions = new HashSet<Transaction>();
    }
}

订单映射:

  <class name="Order" table="Orders">
<cache usage="read-write"/>
<id name="Id">
  <generator class="guid"/>
</id>
<property name="CreatedOn" type="datetime"/>
<property name="Total" type="decimal"/>
<set name="Transactions" table="Transactions" lazy="false" inverse="true">
  <key column="OrderId"/>
  <one-to-many class="Transaction"/>
</set>

交易类:

    public class Transaction {
    public virtual Guid Id { get; set; }
    public virtual DateTime ExecutedOn { get; set; }
    public virtual bool Success { get; set; }

    public virtual Order Order { get; set; }
}

交易映射:

  <class name="Transaction" table="Transactions">
<cache usage="read-write"/>
<id name="Id" column="Id" type="Guid">
  <generator class="guid"/>
</id>
<property name="ExecutedOn" type="datetime"/>
<property name="Success" type="bool"/>
<many-to-one name="Order" class="Order" column="OrderId" not-null="true"/>

我真的不想要双向关联。我的事务对象不需要直接引用它们的订单对象(我只需要访问订单的交易)。但是,我必须添加它,以便Order.Transactions持久保存到数据库:

存储库:

        public void Update(Order entity)
    {
        using (ISession session = NHibernateHelper.OpenSession()) {
            using (ITransaction transaction = session.BeginTransaction()) {
                session.Update(entity);

                foreach (var tx in entity.Transactions) {
                    tx.Order = entity;
                    session.SaveOrUpdate(tx);
                }
                transaction.Commit();
            }
        }
    }

我的问题是,这将为订单集合上的每个交易发出更新(无论它是否已更改)。

我想要解决的是在保存订单之前必须明确保存交易,而只是将交易添加到订单中,然后保存订单:

        public void Can_add_transaction_to_existing_order()
    {
        var orderRepo = new OrderRepository();
        var order = orderRepo.GetById(new Guid("aa3b5d04-c5c8-4ad9-9b3e-9ce73e488a9f"));

        Transaction tx = new Transaction();
        tx.ExecutedOn = DateTime.Now;
        tx.Success = true;

        order.Transactions.Add(tx);

        orderRepo.Update(order);
    }

虽然我发现了很多关于建立一对多关联的文章,但大多数都讨论了检索数据而不是坚持回来。

非常感谢, 本

1 个答案:

答案 0 :(得分:3)

您需要在映射上设置cascade属性,以便将持久性级联到子对象:

<set name="Transactions" table="Transactions" lazy="false" inverse="true" cascade="all-delete-orphan">

您的Order对象应该有一个AddTransaction方法,用于设置子对象的父引用。类似的东西:

public void AddTransaction(Transaction txn)
{
    txn.Order = this;
    Transactions.Add(txn);
}

这将导致在持久化订单时持久化Transaction对象。您可以使用internal修饰符公开Transaction上的Order属性,以使其不公开显示。