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

时间:2015-07-17 08:38:46

标签: c# nhibernate fluent-nhibernate

我们假设有一个实体:

class Book
{
    public Guid ID { get; set; }

    public int Version { get; set; }

    public string Author { get; set; }

    public string Title { get; set; }
}

适当的Fluent NHibernate映射:

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

我希望在Version实例的IStatelessSession.Update()方法调用之后获取Book属性的递增值,以执行另一个实体的相关更新(请参阅注释):< / p>

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. 调用Version方法之前哪些方法可能导致ITransaction.Commit()值增加?

1 个答案:

答案 0 :(得分:2)

上述行为不是随机的。

超过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生成的属性是最新的