【问题标题】:NHibernate PreUpdateEvent firing after the change has been done更改完成后触发 NHibernate PreUpdateEvent
【发布时间】:2014-08-21 07:51:08
【问题描述】:

当我访问PreUpdateEvent 时,我会得到包含更新数据的实体。
我假设预更新会给我数据库中更新之前的数据。

preUpdateEvent.Entity - 提供新数据。 preUpdateEvent.State - 提供新数据。

// Even when I go to the database and ask the persisted entity, 
//  I get it with the changes.
preUpdateEvent.Session.Get(typeof(preUpdateEvent.Entity), preUpdateEvent.Entity.Id);

如何访问OnPreUpdate(PreUpdateEvent preUpdateEvent) 中的持久化实体,以便将其审核到审核表中?

更新

public bool OnPreUpdate(PreUpdateEvent preUpdateEvent)
{
    var persisted = preUpdateEvent.Session.Merge(preUpdateEvent.Entity);
    return false;
}

所以 var 在合并后保留了新数据。
我希望坚持拥有旧数据(更新前)。

【问题讨论】:

    标签: c# nhibernate


    【解决方案1】:

    PreUpdateEvent 监听器被这样调用

    bool OnPreUpdate(PreUpdateEvent @event); 
    

    关于实体的完整信息作为@event 参数传递,该参数的类型为class PreUpdateEvent。所以我们确实有访问属性:

    /// <summary> The entity involved in the database operation. </summary>
    public object Entity { get; }
    /// <summary> The id to be used in the database operation. </summary>
    public object Id { get; }
    /// <summary>
    /// Retrieves the state to be used in the update.
    /// </summary>
    public object[] State { get; }
    /// <summary>
    /// The old state of the entity at the time it was last loaded from the
    /// database; can be null in the case of detached entities.
    /// </summary>
    public object[] OldState { get; }
    

    我们可以获得所有信息,最新的变化(State)和以前的值(OldState)

    在这个阶段(事件)我们不能调用session.get() ...因为已经有“更新的”对象。在这种情况下,会话不会以数据库为目标。

    正如评论所说:OldState,如果对象来自外部世界(客户端、服务层)并通过Update() 传递给会话,则可能为 NULL。为避免这种情况,我们可以致电session.Merge(ourInstance),这将解决很多问题。见:9.4.2. Updating detached objects

    EXTEND:OldState 是如何工作的?

    1) 要么我们通过sessin.GetById(id) 加载对象。 Session 有 hands,而我们正在修改该实例。最后,我们调用session.Flush() 在数据库中执行 UPDATE 语句。在这种情况下,NHibernate 确实可以控制一切……OldState 已正确填充。

    2) 或者我们确实从外部(不是session)世界接收数据,由分离的实例表示。在这种情况下,NHibernate 无法跟踪更改。它只有通过session.Update(instance) 传递的最新信息,并且在 Flush() 上它确实触发了 PreUpdate 事件,但没有旧状态。

    在这种情况下,我们可以调用session.Merge(instance) 而不是Update(),NHibernate 将从数据库中加载对象(因此会有它的以前的值),使用合并实例附带的最新设置更新它们,并使用完整信息触发 PreUpdate 事件。

    【讨论】:

    • 嗨,谢谢,如果我看一下这个踏板:stackoverflow.com/questions/867341/… 它说迭代器是一种遗产......所以如果我留在听众那里。我看到 OldState 为空。无论如何都不能在onpreupdate中获取持久化实体吗?谢谢
    • 不不...必须在您最初调用更新的地方调用合并!这已经太晚了...实际上,Merge 应该替换 Update... session.Flush() (later) 将导致 OnPreUpdate 事件被触发...和 ​​OldState被填充
    • 所以没有办法在 OnPreUpdate 中获取旧状态?
    • +1。好的,我已经将我的主要保存方法设置为使用 Merge。我看到 oldState 现在可用了。我有两个问题。 1) 从保存更改为合并将如何影响我的应用程序? 2) 如何将 OlsState 转换为我的强类型实体?再次感谢...
    • 添加 2) 如何将对象转换为您的强类型...这真的取决于您;) 没有内置的解决方案...要给出第一个的答案,我会告诉你我的故事:我总是调用 Get(id) 并绑定它。所以一切都是开箱即用的。实际上,Merge 的作用是一样的.. 所以没有那么多副作用.. 只是以后可能很难理解您为什么不使用 Update ;) ... 老实说,我创建了自己的非 NHibernate 机制来跟踪更改。从我的角度来看,它是业务功能,不属于数据层..但它是不同的和大故事;)
    【解决方案2】:

    也许在这个新会话中创建新会话并合并对象,你会得到 OldState

    【讨论】:

      猜你喜欢
      • 2016-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-19
      • 1970-01-01
      • 2011-07-06
      • 1970-01-01
      • 2018-04-16
      相关资源
      最近更新 更多