如何使用 NHibernate 插入或更新(或覆盖)记录?
我需要将一行写入数据库,无论它是否已经存在。 在使用 NHibernate 之前,这是通过存储过程完成的。 该过程将尝试更新,如果没有行被修改,它将回退到插入。 这很有效,因为应用程序并不关心记录是否存在。
对于 NHibernate,我发现的解决方案需要加载实体并修改它,或者删除实体以便插入新实体。 应用程序必须关心记录是否已经存在。 有办法解决这个问题吗?
身份证重要吗?
分配的 ID
该对象有一个关键字作为分配的 id,并且是表中的主键。
据我了解,SaveOrUpdate() 将根据 Id 适当调用 Save() 或 Update() 方法。 使用指定的 id,这将不起作用,因为 id 不是未保存的值。 然而,版本或时间戳字段可以用作指示符。 实际上,这并不相关,因为这仅反映内存中的对象是否已与数据库中的记录关联; 它并不表明该记录是否存在于数据库中。
生成的 ID
如果分配的 id 确实是问题的原因,我可以使用生成的 id 而不是关键字作为主键。 这将避免 NHibernate 插入/更新问题,因为它总是有效地插入。 但是,我仍然需要防止重复的关键字。 使用关键字列上的唯一索引,即使主键不同,它仍然会抛出重复关键字的异常。
另一种方法?
也许问题并不在于 NHibernate,而在于其建模方式。 与应用程序的其他领域不同,它更以数据为中心,而不是以对象为中心。 NHibernate 使读/写变得容易并且消除了存储过程,这很好。 但是,不考虑现有值而简单地编写的愿望与对象身份模型的模型不太相符。 有更好的方法来解决这个问题吗?
I need to write a row to the database regardless of whether it already exists or not. Before using NHibernate this was done with a stored procedure. The procedure would attempt an update and if no rows were modified it would fallback to an insert. This worked well because the application doesn't care if the record exists.
With NHibernate, the solutions I have found require loading the entity and modifying it, or deleting the entity so the new one can be inserted. The application does have to care if the record already exists. Is there a way around that?
Does the Id Matter?
Assigned Id
The object has a keyword as an assigned id and is the primary key in the table.
I understand that SaveOrUpdate() will call the Save() or Update() method as appropriate based on the Id. Using an assigned id, this won't work because the id isn't an unsaved-value. However a Version or Timestamp field could be used as an indicator instead. In reality, this isn't relevant because this only reflects on whether the object in memory has been associated with a record in the database; it does not indicate if the record exists or not in the database.
Generated Id
If the assigned id were truly the cause of the problem, I could use a generated id instead of the keyword as the primary key. This would avoid the NHibernate Insert/Update issue as it would effectively always insert. However, I still need to prevent duplicate keywords. With a unique index on the keyword column it will still throw an exception for a duplicate keyword even if the primary key is different.
Another Approach?
Perhaps the problem isn't really with NHibernate, but the way this is modeled. Unlike other areas of the application, this is more data-centric rather object-centric. It is nice that NHibernate makes it easy to read/write and eliminates the stored procedures. But the desire to simply write without regard to existing values doesn't fit well with the model of an object's identity model. Is there a better way to approach this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我正在使用,
但 FindByExample 方法返回所有类似的对象,而不是具有确切 ID 的对象,您有何建议? 因为我只有对象作为参数,所以我无法访问其特定 ID 字段,因此无法使用 session.get(Object.class(), id);
I`m using
but FindByExample method returns all objects alike not objects with the exact ID what do you suggest ? since I have only object as parameter I don't have access to its specific ID field so I cannot use
session.get(Object.class(), id);
通常,NHibernate 可以依靠未保存的值来确定是否应该插入或创建实体。 然而,由于您正在分配 ID,因此 NHibernate 看起来您的实体已经被持久化了。 因此,您需要依靠对象的版本控制来让 NHibernate 知道它是一个新对象。 有关如何对实体进行版本控制的信息,请参阅以下链接:
http://web.archive.org/web/20090831032934/http://devlicio.us/blogs/mike_nichols /archive/2008/07/29/when-flushing-goes-bad-assigned-ids-in-nhibernate.aspx
Typically, NHibernate can rely on the unsaved-value to determine whether it should insert or create the entity. However, since you are assigning the ID, to NHibernate it looks like your entity has already been persisted. Therefore, you need to rely on versioning your object to let NHibernate know that it is a new object. See the following link for how to version your entity:
http://web.archive.org/web/20090831032934/http://devlicio.us/blogs/mike_nichols/archive/2008/07/29/when-flushing-goes-bad-assigned-ids-in-nhibernate.aspx
使用 session.SaveOrUpdate(object) 方法。
Use the session.SaveOrUpdate(object) method.
你可以做
You can do
查询关键字 = x 的对象,取 FirstOrDefault。 如果为空,则添加新对象,如果存在,则更新您获得的对象并对其调用 saveOrUpdate 。
Query objects where keyword = x, take FirstOrDefault. If it's null, Add new object, if it exists, update object that you got and call saveOrUpdate on it.
这对我有用:
实现
实体
我必须创建一个接口(IIdentificableNh),它允许我访问 Id 属性值。
使用示例:
This worked for me:
Implementation
Entity
I had to create an interface (IIdentificableNh) that allows me to access the Id property value.
Usage example:
调用 hibernate.saveOrUpdate() 它将检查该对象是否在数据库中,如果是则更新它,如果不是则保存(即插入)它。
call hibernate.saveOrUpdate() which will check if the object is in the database, update it if it is, and save (i.e. insert) it if it is not.