Nhibernate 在 SaveorUpdate 之前加载覆盖值

Nhibernate load overwriting values before SaveorUpdate

我目前在使我的更新功能正常工作时遇到问题,该功能首先使用 session.Load() 加载一个实体,然后使用 session.SaveorUpdate()

我的问题是,如果我不首先加载会话,nhibernate 将不知道这些关系,因此会尝试插入已经存在的数据,当我首先加载实体时,更新后的实体会被数据已经在数据库中。

public void Update(T Entity, bool load)
{
    using(ISession session = this.helper.GetSession())
    {
        using(ITransaction transaction = session.BeginTransaction())
        {
            if(load)
            {
                session.Load(Entity, Entity.ID);
            }

            session.SaveOrUpdate(Entity);
            transaction.Commit();
            session.Flush(); 
        }
    }
}

简而言之:

  • load object and then bind it with new values (changes will be persisted on session.Flush() without any explicit Update() call) or
  • create new C# instance with bounded values, including ID, and call session.Update(myInstance)

更复杂的答案可以在其中一个文档章节中找到:

9.4.2. Updating detached objects

Many applications need to retrieve an object in one transaction, send it to the UI layer for manipulation, then save the changes in a new transaction. (Applications that use this kind of approach in a high-concurrency environment usually use versioned data to ensure transaction isolation.) This approach requires a slightly different programming model to the one described in the last section. NHibernate supports this model by providing the method ISession.Update().

// in the first session
Cat cat = firstSession.Load<Cat>(catId);
Cat potentialMate = new Cat();
firstSession.Save(potentialMate);

// in a higher tier of the application
cat.Mate = potentialMate;

// later, in a new session
secondSession.Update(cat);  // update cat
secondSession.Update(mate); // update mate

The usage and semantics of SaveOrUpdate() seems to be confusing for new users. Firstly, so long as you are not trying to use instances from one session in another new session, you should not need to use Update() or SaveOrUpdate(). Some whole applications will never use either of these methods.

Usually Update() or SaveOrUpdate() are used in the following scenario:

  • the application loads an object in the first session
  • the object is passed up to the UI tier
  • some modifications are made to the object
  • the object is passed back down to the business logic tier
  • the application persists these modifications by calling Update() in a second session

因此,我们可以在一个会话中获取某个实体的实例...然后关闭该会话。这样的 对象甚至可以是全新的 C# 实例 - 它的所有属性都受到某些上层 的限制(例如 MVC 绑定器或 Web API 格式化程序)

稍后,我们可以使用该实例并调用 session.Update(myInstance)。 NHibernate 将采用该实体的 ID 并发出正确的更新语句。

另一种方法是调用合并:

The last case can be avoided by using Merge(Object o). This method copies the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. The method returns the persistent instance. If the given instance is unsaved or does not exist in the database, NHibernate will save it and return it as a newly persistent instance. Otherwise, the given instance does not become associated with the session. In most applications with detached objects, you need both methods, SaveOrUpdate() and Merge().

the doc

中阅读更多内容