为什么要为对象调用NHibernate OnPreInsert和OnPreUpdate方法

时间:2010-03-02 18:45:28

标签: nhibernate

我在PreSaveEventListener中使用NHibernate OnPreInsert和OnPreUpdate事件来设置我的实体的CreatedDate和ModifiedDate。问题是,有两个实体在我第一次创建时会触发两个事件。 这会导致问题,因为在OnPreInsert事件后实体状态不会被保存,因此OnPreUpdate事件在一个全新的实体状态下运行,而我的CreatedDate永远不会被设置为(默认为01/01 / 0001)。

起初,我认为这是因为我的代码在事务结束之前重新启动了两个SaveOrUpdate调用。果然,我发现了一些这样的代码。但后来我意识到这仍然发生在另一个实体身上。据我所知,只有这两个实体有这个问题。我通过在其构造函数中设置CreatedDate来暂时解决问题,但我想避免这种情况。

这是我的结构:
业务实体(具有两个具体连接子类的抽象类)
BusinessContact实体与业务的多对一关系

编辑:我最近意识到它也发生在另一个对象(InvoiceLineItem)上,但不是几乎相同的对象(BillLineItem)以几乎相同的方式实例化和使用。似乎相当随意。

以前有人见过这个吗?

这是事件监听器代码:

public class PreSaveEventListener : IPreInsertEventListener, IPreUpdateEventListener {
    public bool OnPreInsert(PreInsertEvent @event) {
        EntityWithGuidId entity = @event.Entity as EntityWithGuidId;

        if (null != entity) {
            var createdDate = DateTime.Now;
            var modifiedDate= DateTime.Now;
            Set(@event.Persister, @event.State, "CreatedDate", createdDate);
            Set(@event.Persister, @event.State, "ModifiedDate", modifiedDate);
            entity.CreatedDate = createdDate;
            entity.ModifiedDate = modifiedDate;
        }

        return false;
    }

    public bool OnPreUpdate(PreUpdateEvent @event) {
        EntityWithGuidId entity = @event.Entity as EntityWithGuidId;

        if (null != entity) {
            var modifiedDate= DateTime.Now;
            Set(@event.Persister, @event.State, "ModifiedDate", modifiedDate);
            entity.ModifiedDate = modifiedDate;
        }

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

3 个答案:

答案 0 :(得分:0)

事件监听器在我的项目中引起了很多不同的问题,其中许多对我来说没有意义。我认为你的问题可能是因为NHibernate在创建后真正更新了你的实体。 NHibernate可以更新实体版本或为它设置一些id(或guid)。你能在这里放置已发行实体的映射吗?我还建议你在profiler中查看sql查询。

答案 1 :(得分:0)

我实际上碰到了这个问题,可能会出现同样的问题。

我实现了自己的StringTrimEnd类型处理程序,它在插入数据库之前或检索它们之后修剪了字符串的结尾。

好吧,我实现了Equals方法错误,当x和y为null时,它为Equals(object x, object y)返回false。

因此,当我创建一个带有空字符串的新对象时,它将加载的值(null)与当前值(null)进行比较,并确定需要更新(以及插入)。

也许这会在某些时候帮助某人。

答案 2 :(得分:0)

您在DB中有可空字段,但在NH

中未标记为可为空