Search code examples
c#nhibernatecastle-activerecordevent-listener

NHibernate EventListeners - getting the value of a property of the entity being saved


I'm implementing a custom EventListener to save auditing information in NHibernate.

I'm currently extending DefaultSaveOrUpdateEventListener, overriding PerformSaveOrUpdate, going through the properties of each entity and saving them elsewhere.

This works with simple properties, but fails when cascade-saving a one-to-many relationship.

If I take the following entities:

[ActiveRecord]
public class Child
{
    [PrimaryKey(PrimaryKeyType.GuidComb)]
    public Guid Id { get; set; }

    [BelongsTo]
    public Parent Parent { get; set; }
}

[ActiveRecord]
public class Parent
{
    [PrimaryKey(PrimaryKeyType.GuidComb)]
    public Guid Id { get; set; }

    [HasMany(Cascade = ManyRelationCascadeEnum.SaveUpdate)]
    public IList<Child> Children { get; set; }
}

And then save a parent with a child:

ActiveRecordMediator<Parent>.Save(new Parent
{
    Children = new List<Child>
    {
        new Child()
    }
});

The child will get the correct parent assigned to it when its persisted to the database but the 'Parent' property of the child is null when my EventListener is called.

How can I get the value that will actually be persisted to the database in this case?

[EDIT] I've recently been looking at getting this to work by hooking the cascade and seeing what else was being saved at the time, but that seems horribly unreliable and I'd much prefer to get the data out of NHibernate so I know it's consistent with the database.


Solution

  • I'm not sure how you can accomplish this with ActiveRecord but it has to do with the mechanism in which NHibernate persists parent/child relationships.

    Saving the child cascade prior to saving the parent in NHibernate is by design depending on which end of the relationship is marked as "inverse=true" and the child needs to have a "not-null=true" attribute on the element (which determines which end owns the relationship). This will make it so the Child is managing the state of the relationship.

    Then you can simply save the child, and the parent will be updated with the appropriate information. This will generate one INSERT statement, instead of an INSERT AND UPDATE that you are probably seeing now. Not sure if this solves your problem, but I believe the problem you are having is around this behavior. You can read more at this link:

    https://www.hibernate.org/hib_docs/nhibernate/html/example-parentchild.html