views:

35

answers:

1

I have an Animal class that implements IDomainObject. There is another class, Cat, that inherits from Animal. I'm using a Table Per Subclass inheritance strategy for my NHibernate mappings and map the CreatedDate and LastModified properties to columns in the Animal table and to columns in the Cat table.

I also use a PreUpdate event handler to assign LastModified with a value.

When I update a property in a Cat object, two UPDATES get sent to the database: one for Animal and one for Cat. However, the UPDATE for Animal is the one that gets the new LastModified value, and the UPDATE for Cat keeps the old value.

This causes some issues when the Cat entity is retrieved again in another Session. It seems that LastModified gets overwritten with the new value (from Animal), effectively marking the entity has dirty, and triggering another UPDATE.

There seems to be something wrong with my overall design, but I'm not sure what it is. What is a better way to go about this?

public class Animal : IDomainObject {
    // ... various properties

    public virtual DateTime CreatedDate { get; set; }
    public virtual DateTime LastModified { get; set; }
    public virtual int Version { get; protected set; }
}

public class Cat : Animal {
    // ... various properties

    public override DateTime CreatedDate { get; set; }
    public override DateTime LastModified { get; set; }
    public override int Version { get; protected set; }
}

public interface IDomainObject {
    DateTime CreatedDate { get; set; }

    DateTime LastModified { get; set; }

    int Version { get; }
}

public bool OnPreUpdate(PreUpdateEvent eventItem) {
    if (!(eventItem.Entity is IDomainObject)) {
        return false;
    }

    var entity = eventItem.Entity as IDomainObject;

    if (entity == null) {
        return false;
    }

    var lastModified = DateTime.Now;

    PersistState(eventItem.Persister, eventItem.State, "LastModified", lastModified);

    entity.LastModified = lastModified;

    return false;
}

private void PersistState(IEntityPersister persister, object[] state, string propertyName, object value) {
    var index = Array.IndexOf(persister.PropertyNames, propertyName);

    if (index == -1) {
        return;
    }

    state[index] = value;
}
+2  A: 

Two things I don't understand:

  1. Why do you override CreatedDate, LastModified and Version in your Cat-class - when they have no new functionality?

  2. Why do you have those three columns in both tables?

It should be enough to have the three columns/properties in the baseclass - anything else is asking for trouble.

Goblin
+1: There is no good reason to not just leave these in the base class.
DanP
This makes complete sense. Thanks.
Chris Dwyer