简体   繁体   English

NHibernate更新无效

[英]NHibernate Update Not working

I can't get my update to work. 我无法让我的更新工作。 The test fails and I do not see any update statements being sent to the database. 测试失败,我没有看到任何更新语句被发送到数据库。 Can someone tell me what I'm doing wrong? 有人能告诉我我做错了什么吗?

This is my repository update procedure: 这是我的存储库更新过程:

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

This is the unit test I am trying: 这是我正在尝试的单元测试:

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

The test always fails. 测试总是失败。 I see the test data being inserted and I see the select for the test.I don't see the update being performed. 我看到插入的测试数据,我看到测试的选择。我没有看到正在执行的更新。 What am I missing? 我错过了什么?

Thanks! 谢谢!

There are a couple of things that may be happening. 可能会发生一些事情。

1) The update is failing and NHibernate is raising an exception that is being swallowed somewhere - that can happen depending on how you've configured things. 1)更新失败了,NHibernate引发了一个被某个地方吞噬的异常 - 这可能会发生,具体取决于你配置的方式。 So in VS make sure all exceptions will cause a break. 所以在VS中确保所有异常都会导致中断。

2) The update is being cached and not written directly to the DB - you can force data to be written using Repository.Flush(); 2)更新正在缓存而不是直接写入数据库 - 您可以使用Repository.Flush();强制写入数据Repository.Flush();

3) Are you sure _projects[0] has been read from the DB - I'm assuming that's happening in a TestSetup? 3)你确定已经从数据库中读取了_projects [0] - 我假设这是在TestSetup中发生的吗? If not NHibernate won't be aware of that as an object which is under its 'control'. 如果不是NHibernate将不会将其视为一个处于“控制”之下的对象。

BTW - It's good practise to read the data you are going to change within the test itself, and then undo that change, resetting the DB to it's original state. 顺便说一句 - 最好在测试中读取您要更改的数据,然后撤消该更改,将数据库重置为原始状态。 In that way your test DB won't be altered by your testing. 这样,您的测试数据库将不会被您的测试更改。

BTW2 - In the above test, if project.Name has already been updated once, ie the test has run succesfully. BTW2 - 在上面的测试中,如果project.Name已经更新一次,即测试已经成功运行。 Then next time around the test will suceed even if the update itself fails. 然后,即使更新本身失败,下次测试也会成功。 A way to avoid this - append a DateTime to the project.Name, don't set it to a fixed value. 一种避免这种情况的方法 - 将DateTime附加到project.Name,不要将其设置为固定值。

Another thing is this: when you save an entity using a session and you load the same entity from the same session using the entity's ID, you will get the same instance that you saved - regardless of whether any inserts or updates have been issued to the database. 另一件事是:当您使用会话保存实体并使用实体的ID从同一会话加载相同的实体时,您将获得您保存的相同实例 - 无论是否已向其发出任何插入或更新数据库。

That's because of NHibernate's 1st level cache, which is an identity map that belongs to the session. 那是因为NHibernate的第一级缓存,它是属于会话的身份映射。

If you want your test to check what was actually written to the database, you may do it like so: 如果您希望测试检查实际写入数据库的内容,您可以这样做:

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

ISession.Update in NHibernate does not commit changes to the database. NHibernate中的ISession.Update不会提交对数据库的更改。 It is used to update transient instances in a different session from the one that was used to retrieve the instance (see here for details). 它用于更新与用于检索实例的会话不同的会话中的瞬态实例(有关详细信息,请参见此处 )。 Changes are sent to the database when a session is flushed. 刷新会话时,会将更改发送到数据库。 By default, sessions operate in FlushOnCommit mode, which means the changes to the objects will be sent to the database when the NHibernate transaction is committed (see here for details on the different flush modes). 默认情况下,会话以FlushOnCommit模式运行,这意味着在提交NHibernate事务时,对象的更改将被发送到数据库(有关不同刷新模式的详细信息,请参见此处 )。

try this may be i am wrong but its works 试试这可能是我错了,但它的作品

public void UpdateProject(Project proj)
 {
    ISessionFactory SessionFactory;

    ISession session = SessionFactory.OpenSession();

    using (ITransaction transaction = session.BeginTransaction())
    {

      session.Update(proj);
      transaction.Commit();

    }
 }

FlushMode ! FlushMode

I'm maintaining an app I did not write and found out the hard way that even if you use a transaction and call txn.Commit() you still may not see the changes if your NHibernate Session has session.FlushMode = FlushMode.Never . 我正在维护一个我没有编写的应用程序,并且发现即使您使用事务并调用txn.Commit() ,如果您的NHibernate会话具有session.FlushMode = FlushMode.Never txn.Commit()您仍然可能看不到更改。

Very easy to detect. 很容易检测到。 Set a breakpoint and look at session.FlushMode . 设置断点并查看session.FlushMode Or just search all *.cs files for FlushMode. 或者只搜索FlushMode的所有* .cs文件。

I recently hit this same issue. 我最近遇到了同样的问题。

  1. Inserts Worked 工作插入
  2. Updates Did Not 更新没有

The issue was a flaw in the coding. 这个问题是编码中的一个缺陷。 Data was checked if the row was changed, then a new entity was mapped, and an update was sent, but nothing happened. 检查数据是否更改了行,然后映射了新实体,并发送了更新,但没有任何反应。

Solution: The actual row had to be queried from the database, then changes in C# applied to that row that was pulled back. 解决方案:必须从数据库中查询实际行,然后将C#中的更改应用于已撤回的该行。 Now NHibernate knows the row changed, run save and all worked. 现在NHibernate知道行已更改,运行save并且一切正常。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM