views:

35

answers:

2

I'm using Ayende's method (http://ayende.com/Blog/archive/2009/04/29/nhibernate-ipreupdateeventlistener-amp-ipreinserteventlistener.aspx) to set the create and update date on entities with Listeners, but it's only setting them for the entity being affected, not anything else in the unit of work.

So, for example, if I do this:

Order order = repository.Get<Order>(1);
order.AddNote(new Note("this is a note"));
repository.SaveOrUpdate(order);

The Note gets a create/update date, but the order does not. Are there any tricks to getting the entire unit of work to show an update? Or do I physically have to update a property on the order to get that update date set?

If it make any difference, I'm also using S#arp Architecture.

Here's the code block I'm using:

public class AuditEventListener : IPreUpdateEventListener, IPreInsertEventListener
{
    public bool OnPreUpdate(PreUpdateEvent @event)
    {
        var audit = @event.Entity as AuditedEntity;
        if (audit == null)
            return false;

        var time = DateTime.Now;

        Set(@event.Persister, @event.State, "UpdateDate", time);

        audit.UpdateDate = time;
        return false;
    }

    public bool OnPreInsert(PreInsertEvent @event)
    {
        var audit = @event.Entity as AuditedEntity;
        if (audit == null)
            return false;


        var time = DateTime.Now;

        Set(@event.Persister, @event.State, "CreateDate", time);
        Set(@event.Persister, @event.State, "UpdatedDate", time);

        audit.CreateDate= time;
        audit.UpdateDate= time;

        return false;
    }

    private void Set(IEntityPersister persister, object[] state, string propertyName, object value)
    {
        var index = Array.IndexOf(persister.PropertyNames, propertyName);
        if (index == -1)
            return;
        state[index] = value;
    }
}
+2  A: 

If I'm not mistaken and the Notes collection is inverse, order is not dirty, which is why it's not being saved and, therefore, not firing the PreUpdate event.

So yes... you'll have to "touch" order if you want to force an update.

Diego Mijelshon
That solved it. Thank you. Now I have to figure out how to tell the order it's dirty...
Jamie
Well, you can manually change the UpdateTime...
Diego Mijelshon
Do you know how to get ahold of the Order object? In the OnPreInsert/OnPreUpdate, I have the @event object, that is the OrderNote. If I debug, I can see the Order object (by looking at the @event properties), but I'd like to dynamically set the UpdateTime on the order for any updates to objects associated with the Order...Something like: (@event.Entity as IHasOrder).Order.UpdateDate = DateTime.Now;I guess that would work, actually... but I have to litter a bunch of entities with IHasOrder... anything that belongs to an order...
Jamie
By "manually" I meant *really manually*. The OnPreInsert/Update event is too late to change the parent entity.
Diego Mijelshon
A: 

So, Diego was correct that the order had to be touched to be updated. What I ended up doing was adding an interface IBelongToOrder to anything that was part of the order:

public interface IBelongToOrder
{
    Order Order { get; set; }
}

Then, all of the collections on the order implemented this interface. Lastly, the OnPreInsert/Update just checked for this interface and updated accordingly, like:

var orderChild = @event.Entity as IBelongToOrder;
if (orderChild != null)
{
    orderChild.Order.UpdateDate = DateTime.Now;
}

Hope this helps someone else out trying to figure out how to update collections in a unit of work...

Jamie