Saving child collections with NHibernate

Posted by Ben on Stack Overflow See other posts from Stack Overflow or by Ben
Published on 2010-04-14T12:23:54Z Indexed on 2010/04/14 12:33 UTC
Read the original article Hit count: 338

Hi,

I am in the process or learning NHibernate so bare with me.

I have an Order class and a Transaction class. Order has a one to many association with transaction. The transaction table in my database has a not null constraint on the OrderId foreign key.

Order class:

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

Order Mapping:

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

Transaction Class:

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

Transaction Mapping:

  <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"/>

Really I don't want a bidirectional association. There is no need for my transaction objects to reference their order object directly (I just need to access the transactions of an order). However, I had to add this so that Order.Transactions is persisted to the database:

Repository:

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

My problem is that this will then issue an update for every transaction on the order collection (regardless of whether it has changed or not).

What I was trying to get around was having to explicitly save the transaction before saving the order and instead just add the transactions to the order and then save the order:

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

Although I have found quite a few articles covering the set up of a one-to-many association, most of these discuss retrieving of data and not persisting back.

Many thanks, Ben

© Stack Overflow or respective owner

Related posts about nhibernate

Related posts about nhibernate-mapping