NHibernate 为新实体生成 INSERT 和 UPDATE

Posted

技术标签:

【中文标题】NHibernate 为新实体生成 INSERT 和 UPDATE【英文标题】:NHibernate generates INSERT and UPDATE for new entity 【发布时间】:2013-11-16 16:42:22 【问题描述】:

我有一个使用 Hilo 生成的带有 Id 列的实体。 我有一个事务,创建一个新实体并调用 SaveOrUpdate() 以获取 Hilo 生成的实体 ID(我需要将该 ID 写入另一个数据库)。

稍后,在同一个事务中,我更新了新实体,只是简单地更新了一个简单的属性,最后我再次调用了 SaveOrUpdate()。

我看到生成的 SQL 命令首先是 INSERT,然后是 UPDATE,但我想要的只是一个带有实体最终详细信息的 INSERT。那可能吗?我是不是做错了什么?

编辑:添加代码示例

这是一个非常简化的伪代码示例:

Person newPerson = new Person(); // Person is a mapped entity
newPerson.Name = "foo";
_session.SaveOrUpdate(newPerson); // generates INSERT statement

newPerson.BirthDate = DateTime.Now;
_session.SaveOrUpdate(newPerson); // generates UPDATE statement

// assume session transaction was opened before and disposed correctly for sake of simplicity
_session.Transaction.Commit();

【问题讨论】:

【参考方案1】:

关键是使用像 NHibernate 这样的 ORM 工具,我们以不同的方式工作,然后我们使用 ADO.NET

虽然 ADO.NET Commands 和它们的 Execute() 方法系列会导致在 DB 服务器上立即执行 SQL 语句……但 NHibernate 却截然不同。

我们正在与ISession 合作。会话,可以被认为是内存中的 C# 集合。所有Save()SaveOrUdpate()Update()Delete() ... 调用都是针对该对象表示执行的。没有执行 SQL 命令,在调用这些方法时,目前没有 低级 ADO.NET 调用。

抽象允许 NHibernate 优化最终的 SQL 语句批处理...基于在 ISession 中收集的所有信息。这就是为什么,如果使用 Session,您将永远不会看到 INSERT、UPDATE,除非我们明确调用神奇的 Flush() 或完全更改 FlushMode。

在那种情况下(调用Flush()),我们想说:NHibernate 我们已经足够聪明了,现在是执行命令的时候了。在其他情况下,通常将其留在 NHibernate 上就足够了...

请看这里: - 9.6. Flush

【讨论】:

我了解 Flush() 的机制,我只是期望在同一会话中插入实体然后更新的优化行为,只会生成一个带有最终值的 INSERT 语句实体。 这一切都取决于您拥有的映射。如果 NHibernate 可以在单个插入中做到这一点,那么在大多数情况下都会以这种方式完成。但老实说......如果你在一个事务中并且在一个会话中...... Save() 就足以被调用。因为那时,在您使用瞬态对象之前,所有更改仍会应用到那个“未保存”的对象中。 fulsh 将保存最终版本。如果有显式调用 insert.. 这可能意味着,一些其他依赖项会强制执行该操作(关系)等。

以上是关于NHibernate 为新实体生成 INSERT 和 UPDATE的主要内容,如果未能解决你的问题,请参考以下文章

NHibernate生成实体类xml映射文件

ORM篇——使用NHibernate配置对象实体的一些小问题

Fluent NHibernate 自动映射:一对多实体,多对多后端?

将原生 SQL where 子句应用于实体的 Nhibernate 查询

NHIbernate 的替代品?

NHibernate 数字格式问题 - 我在哪里设置文化?