NHibernate:在更新实体后获取版本属性的增量值

本文关键字:属性 版本 获取 更新 实体 NHibernate | 更新日期: 2023-09-27 18:03:15

假设存在一个实体:

class Book
{
    public Guid ID { get; set; }
    public int Version { get; set; }
    public string Author { get; set; }
    public string Title { get; set; }
}

合适的Fluent NHibernate-mapping:

class BookMapping : ClassMap<Book>
{
    public BookMapping()
    {
        Id(x => x.ID).GeneratedBy.GuidComb();
        Version(x => x.Version);
        Map(x => x.Author);
        Map(x => x.Title);
    }
}

我想在IStatelessSession.Update()方法调用Book实例后获得Version属性的增量值,以执行另一个实体的相关更新(参见注释):

using (var session = sessionFactory.OpenStatelessSession())
{
    using (var transaction = session.BeginTransaction())
    {
        session.Update(book);
        // Is it safe to use the value of the book.Version property here?
        //
        // Just for example:
        // bookReference.ID = book.ID;
        // bookReference.Version = book.Version; // I would like to have the latest (incremented) version here.
        // session.Insert(bookReference);
        transaction.Commit();
    }
}

当前调试显示它按预期工作。但是我没有找到说明这种行为的文档,即增加IStatelessSession.Update()方法调用后的版本值,由NHibernate保证

  1. 能否提供相应官方文件的参考?有这样的保证吗?
  2. 在调用ITransaction.Commit()方法之前,哪些方法可以导致Version的值增加?

NHibernate:在更新实体后获取版本属性的增量值

上述行为不是随机的。

大于doc (不确定)可能是为了观察代码。任何实体的更新最后都委托给:

EntityUpdateAction.cs

它的方法 Execute() 如下(只是重要部分)

public override void Execute()
{
    ... // some importan stuff
    // here the UPDATE is executed
    if (!veto)
    {
        persister.Update(id, state, dirtyFields, hasDirtyCollection, 
                         previousState, previousVersion, instance, null, session);
    }
    EntityEntry entry = Session.PersistenceContext.GetEntry(instance);
    if (entry == null)
    {
        throw new AssertionFailure("Possible nonthreadsafe access to session");
    }
    // HERE we can see that NHibernate is going for GENERATED properties
    // imeditally 
    if (entry.Status == Status.Loaded || persister.IsVersionPropertyGenerated)
    {
        // get the updated snapshot of the entity state by cloning current state;
        // it is safe to copy in place, since by this time no-one else (should have)
        // has a reference  to the array
        TypeHelper.DeepCopy(state, persister.PropertyTypes,
                            persister.PropertyCheckability, state, Session);
        if (persister.HasUpdateGeneratedProperties)
        {
            // this entity defines property generation, so process those generated
            // values...
            persister.ProcessUpdateGeneratedProperties(id, instance, state, Session);

IPersister方法 ProcessUpdateGeneratedProperties() 描述:

/// <summary>
/// Perform a select to retrieve the values of any generated properties
/// back from the database, injecting these generated values into the
/// given entity as well as writing this state to the persistence context.
/// </summary>
/// <remarks>
/// Note, that because we update the persistence context here, callers
/// need to take care that they have already written the initial snapshot
/// to the persistence context before calling this method. 
/// </remarks>
/// <param name="id">The entity's id value.</param>
/// <param name="entity">The entity for which to get the state.</param>
/// <param name="state">The entity state (at the time of Save).</param>
/// <param name="session">The session.</param>
void ProcessUpdateGeneratedProperties(object id, object entity, 
         object[] state, ISessionImplementor session);

所以,可以肯定的是,你所经历的行为不是随机的。它是由事实驱动的,即有生成的属性——由DB生成。NHibernate总是在每次更新后重新加载这些…

要触摸第二部分,唯一调用它的地方是: session.Flush() 。这可能是提交的一部分,但实际上取决于SessionFlush Mode (甚至可以是 Never ,我们必须/可以手动完成)。无论如何,一旦真正的DB UPDATE被触发,它将进入上述包中,并且我们可以确定,DB生成的属性是最新的