Question

How to go about getting the link entity (foreign key) value in nhibernate when using event listeners to implement audit logging. I am able to log all entity properties except for the link entity, which just log the name of the link entity instead of the value.

It would be great if somebody could point me in the right direction or provide sample code. Here is what I have currently.

public void OnPostInsert(PostInsertEvent @event)
{
        if (@event.Entity is AuditLog)
        {
            return;
        }

        ISession session = @event.Session.GetSession(EntityMode.Poco);
        string username = httpContextHelper.GetCurrentUsersLoginName();
        var props = @event.State;

        for (int i = 0; i < props.Length; i++)
        {
            string newValue = string.Empty;

            //Tried this but obj always null............

            //var obj = props[i] as INHibernateProxy;
            //if (obj != null)
            //{
            //   newValue = obj.HibernateLazyInitializer.Identifier.ToString();
            //   session.Evict(props[i]);
            //}

            newValue = (props[i] == null) ? string.Empty : props[i].ToString();

            if (props[i] != null)
            {
                session.Save(new AuditLog
                {
                    AuditEntryType = "Insert",
                    DomainFullName = @event.Entity.GetType().FullName,
                    DomainShortName = @event.Entity.GetType().Name,
                    OldValue = string.Empty,
                    FieldName = @event.Persister.PropertyNames[i],
                    NewValue = newValue,
                    DomainId = (int)@event.Id,
                    Timestamp = DateTime.Now,
                    Username = username
                });
            }
        }
    }

No correct solution

OTHER TIPS

Does your linked object property reference the linked object itself, or the ID value?

If your property is the linked object, your method will simply call the .ToString() method on the linked object, which is by default the class name. If you were logging a Blog from the below example, the Author would be simply the class name like "MyNamespace.Author", or whatever you output when overriding .ToString().

public class Blog
{
    public virtual int ID {get;set;} 

    public virtual string Name {get;set;}

    public virtual Author Author {get;set;}

    // more properties
}

public class Author
{
    public virtual int ID {get;set;} 

    public virtual string Name {get;set;}

    public virtual DateTime Birthday {get;set;}
}

// property design as used with XML mappings

You have multiple options:

  • Add another property with the Foreign ID, such as "int AuthorID", and map it to the FK column
  • Use a .ToString() implementation which allows you to identify the related object (human readable only).
  • Get the object's ID, like "blogToLog.Author.ID". This has some downsides: you need a special case in your logging routine, logging may call lazy load on the related object (meaning: load from DB only for logging), if not already loaded.
  • Create an interface with an ID property, let all your persistent classes implement it, and if your property is a class type, cast into it and output the ID.

Why dont get the property value by name in @event.Entity. Im not sure where the names are in hibernate, because cheking my src in nhibernate (c#) is a parameter called propertyNames i can get them using reflection.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top