C# NHibernate 更新不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/478827/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 04:58:01  来源:igfitidea点击:

NHibernate Update Not working

c#asp.net-mvcnhibernateorm

提问by

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!

谢谢!

回答by MrTelly

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. So in VS make sure all exceptions will cause a break.

1) 更新失败并且 NHibernate 引发了一个异常,该异常正在某处被吞下 - 这可能会发生,具体取决于您如何配置事物。所以在 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();

3) Are you sure _projects[0] has been read from the DB - I'm assuming that's happening in a TestSetup? If not NHibernate won't be aware of that as an object which is under its 'control'.

3) 您确定 _projects[0] 已从数据库中读取 - 我假设这是在 TestSetup 中发生的吗?如果不是,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. 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.

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

回答by mookid8000

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

回答by Sean Carpenter

ISession.Updatein NHibernate does not commit changes to the database. It is used to update transient instances in a different session from the one that was used to retrieve the instance (see herefor 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 herefor details on the different flush modes).

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

回答by Amol Shiledar

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

    }
 }

回答by Jess

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.

Very easy to detect. Set a breakpoint and look at session.FlushMode. Or just search all *.cs files for FlushMode.

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

回答by Patrick

I recently hit this same issue.

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

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

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. Now NHibernate knows the row changed, run save and all worked.

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

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