【问题标题】:NHibernate: get the incremented value of version property after updating the entityNHibernate:更新实体后获取版本属性的增量值
【发布时间】:2015-07-17 08:38:46
【问题描述】:

假设,有一个实体:

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

我想在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 值增加?

【问题讨论】:

标签: c# nhibernate fluent-nhibernate


【解决方案1】:

上述行为不是随机的。

超过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 模式(甚至可以是 Never,我们必须/可以手动完成)。无论如何,一旦真正的 DB UPDATE 被触发,它就会进入上面的包中,我们可以确定,DB 生成的属性是最新的

【讨论】:

    猜你喜欢
    • 2019-02-15
    • 1970-01-01
    • 1970-01-01
    • 2020-10-10
    • 1970-01-01
    • 1970-01-01
    • 2011-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多