【问题标题】:NHibernate Update Not workingNHibernate 更新不起作用
【发布时间】:2010-10-03 11:47:06
【问题描述】:

我的更新无法正常工作。测试失败,我没有看到任何更新语句被发送到数据库。谁能告诉我我做错了什么?

这是我的存储库更新过程:

public void UpdateProject(Project proj)
{
    Session.Update(proj);
}

这是我正在尝试的单元测试:

[Test]
public void Can_Update_A_Project()
{
    var project = _projects[0];
    project.Name = "test project";

    repository.UpdateProject(project);

    var fromDb = repository.GetAProject(_projects[0].ID);
    Assert.AreEqual(project.Name, fromDb.Name);        
}

测试总是失败。我看到正在插入测试数据,并且看到了测试的选择。我没有看到正在执行更新。我错过了什么?

谢谢!

【问题讨论】:

    标签: c# asp.net-mvc nhibernate orm


    【解决方案1】:

    可能会发生一些事情。

    1) 更新失败并且 NHibernate 引发了一个异常,该异常正在某个地方被吞没 - 这可能会发生,具体取决于您的配置方式。所以在 VS 中确保所有异常都会导致中断。

    2) 更新被缓存而不是直接写入数据库 - 您可以使用 Repository.Flush(); 强制写入数据

    3) 您确定 _projects[0] 已从数据库中读取 - 我假设这是在 TestSetup 中发生的吗?如果不是,NHibernate 将不会意识到这是一个受其“控制”的对象。

    顺便说一句 - 最好在测试本身中读取您要更改的数据,然后撤消该更改,将数据库重置为原始状态。这样,您的测试数据库就不会被您的测试改变。

    BTW2 - 在上述测试中,如果 project.Name 已经更新过一次,即测试已经成功运行。然后,即使更新本身失败,下次测试也会成功。避免这种情况的方法 - 将 DateTime 附加到 project.Name,不要将其设置为固定值。

    【讨论】:

    • 我相信第二个选项(调用flush)确实是解决方案。 :)
    • 对我来说也是同样的情况。我需要刷新会话Session.Flush();
    • Session.Flush() 将立即对数据库进行写入,并使您的测试按预期工作。不建议在 PROD 代码中调用 Session.Flush(),但是最好使用事务来代替。如果没有明确的事务管理,NHibernate 会为您隐式创建事务,这可能会导致问题。 nhprof.com/Learn/Alerts/DoNotUseImplicitTransactions
    【解决方案2】:

    另一件事是:当您使用会话保存实体并使用实体的 ID 从同一会话加载相同的实体时,您将获得与您保存的相同的实例 - 无论是否已插入或更新发布到数据库。

    这是因为 NHibernate 的一级缓存,它是属于会话的身份映射。

    如果您希望您的测试检查实际写入数据库的内容,您可以这样做:

    session.Save(someEntity);
    session.Flush(); // forces the entity to be inserted
    session.Clear(); // clears the session's identity map, thus
                     // detaching someEntity from the session
    
    var loadedEntity = session.Get<EntityType>(someEntity.Id);
    
    // now you may compare the fields of someEntity and loadedEntity
    // to verify that they were actually persisted
    

    【讨论】:

      【解决方案3】:

      NHibernate 中的ISession.Update 不会将更改提交到数据库。它用于在与用于检索实例的会话不同的会话中更新瞬态实例(有关详细信息,请参阅here)。刷新会话时会将更改发送到数据库。默认情况下,会话在 FlushOnCommit 模式下运行,这意味着当 NHibernate 事务提交时,对对象的更改将发送到数据库(有关不同刷新模式的详细信息,请参阅here)。

      【讨论】:

        【解决方案4】:

        试试这个可能是我错了,但它的工作原理

        公共无效更新项目(项目项目) { ISessionFactory 会话工厂; ISession 会话 = SessionFactory.OpenSession(); 使用 (ITransaction 事务 = session.BeginTransaction()) { 会话.更新(项目); 事务.Commit(); } }

        【讨论】:

          【解决方案5】:

          FlushMode!

          我正在维护一个我没有编写的应用程序,并发现即使您使用事务并调用txn.Commit(),如果您的 NHibernate 会话具有 session.FlushMode = FlushMode.Never

          很容易被发现。设置断点并查看session.FlushMode。或者只是在所有 *.cs 文件中搜索 FlushMode。

          【讨论】:

            【解决方案6】:

            我最近遇到了同样的问题。

            1. 插入工作
            2. 没有更新

            问题在于编码中的缺陷。如果行发生更改,则检查数据,然后映射新实体并发送更新,但什么也没发生。

            解决方案:必须从数据库中查询实际行,然后将 C# 中的更改应用于被拉回的行。现在 NHibernate 知道行已更改,运行保存并一切正常。

              public void SaveChanges()
              {
                  _session.Flush();
                  _session.Transaction.Commit();
                  _session.BeginTransaction();
              }
            

            【讨论】:

              猜你喜欢
              • 2023-03-31
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-01-19
              • 1970-01-01
              • 1970-01-01
              • 2016-08-04
              • 2015-08-24
              相关资源
              最近更新 更多