简体   繁体   English

NHibernate在使用session.SaveOrUpdate时重用标识符

[英]NHibernate re-using identifiers when using session.SaveOrUpdate

I have a client who's been running a program of mine for a couple of years now who started getting strange errors. 我有一个已经运行我的程序几年的客户,现在开始出现奇怪的错误。 My application throws exceptions with this in it: 我的应用程序在其中抛出异常:

Cannot insert duplicate key in object

Since I didn't touch the code in literally years, this confused me a lot. 由于我从字面上没有接触代码,这让我很困惑。 And it only happened sometimes. 而且只是偶尔发生。

After A LOT of debugging and pulling out my hair, I figured out what is happening. 经过大量调试并拔出头发后,我才知道发生了什么。

In the code that adds items to the database, I call session.SaveOrUpdate . 在将项目添加到数据库的代码中,我称为session.SaveOrUpdate

I can't recall a specific reason i chose this over the expected session.Save method, but let's continue. 我不记得在预期的session.Save方法中选择此选项的特定原因,但让我们继续。 (i am changing this for the client's code though). (尽管我正在为客户的代码更改此设置)。

So what seems to be happening is that the SaveOrUpdate is re-using existing object's ID's and completely overriding the existing item. 因此,似乎正在发生的事情是, SaveOrUpdate正在重新使用现有对象的ID,并完全覆盖现有项目。 My code throws an error, but the new item is saved to the DB and there is no trace of the original record any longer. 我的代码抛出错误,但是新项已保存到数据库,并且不再有原始记录的痕迹。 In my nhibernate mapping documents I am using the hilo generator for object IDs. 在我的nhibernate映射文档中,我将hilo生成器用于对象ID。

I am guessing this is only happening because there are now enough items in the DB to make the IDs restart or something, i don't know. 我猜这只是在发生,因为数据库中现在有足够的项目可以使ID重新启动,或者我不知道。 I do have an audit table that has/had A LOT of records in it. 我确实有一个审计表,其中有/有很多记录。 10,000's. 10,000个。 But i truncated that table to make backups smaller. 但是我删去了那个表以减少备份。 (could this have causes this problem). (这可能导致此问题)。

I'm trying to find out if anyone can conclusively state if the SaveOrUpdate does for some reason re-use existing IDs or why changing the call to just Save works now. 我试图找出是否有人可以确定性地说明SaveOrUpdate是否确实出于某种原因重用了现有ID,或者为什么将调用更改为Save可以正常工作。 If this is a known issue i will sleep easy, if not, i need to further debug to see if there isn't still some situation where my client will lose data. 如果这是一个已知问题,我会安然入睡,否则,我需要进一步调试以查看是否仍然没有客户端丢失数据的情况。

My code is running Nhibernate 3.3.3.4000, which was the latest code when i wrote this app. 我的代码正在运行Nhibernate 3.3.3.4000,这是我编写此应用程序时的最新代码。

Update 1 更新1

Session.Save is also re-using ID's. Session.Save也正在重复使用ID。

I keep getting duplicate key errors, when inserting new records. 插入新记录时,我不断收到重复的键错误。 But not every time, only some times. 但不是每次都这样。 So it's quite random, which makes it hard to debug. 因此,它是相当随机的,这使得调试变得很困难。

NHibernate users have requested a general purpose method that either saves a transient instance by generating a new identifier or update the persistent state associated with its current identifier. NHibernate用户要求一种通用方法,该方法要么通过生成新标识符来保存瞬态实例,要么更新与其当前标识符关联的持久状态。 The SaveOrUpdate() method now implements this functionality. 现在,SaveOrUpdate()方法实现了此功能。

http://nhibernate.info/doc/nh/en/index.html#manipulatingdata-updating-detached ) http://nhibernate.info/doc/nh/zh-CN/index.html#manipulatingdata-updating-detached

Based on this, you're hypothesis regarding the behaviour of SaveOrUpdate() would stand if NH allocated the object's key before testing whether or not it's 'transient' or 'persisted'. 基于此,您可以假设,如果NH在测试对象的键是“瞬态”还是“持久”之前分配了对象的键,则SaveOrUpdate()的行为将成立。 Ie the key generator allocates a key that happens to be used and then the save or update logic favours update as it determine's the object is 'persistent'. 也就是说,密钥生成器会分配一个碰巧会被使用的密钥,然后保存或更新逻辑会支持更新,因为它确定对象是“持久的”。 I would be surprised if this is what's actually happening as it seems quite a basic mistake to make. 如果这是实际发生的事情,我会感到惊讶,因为这似乎是一个很基本的错误。

If you enable logging, you'll be able to determine whether this is actually the case or not. 如果启用日志记录,则可以确定是否确实如此。

I spent many hours to try and figure out this issue, but i sort of gave up in the end. 我花了很多时间试图弄清楚这个问题,但最终我还是放弃了。

My solution, which seems to work so far, was to change the nhibernate id generator class from hilo to native . 我的解决方案到目前为止似乎仍然有效,是将nhibernate id generator类从hilonative

This did require me to export and re-import all my data so that I could rebuild the tables however, so may not be a great solution for others who find this post, unless they change the identity on the tables manually. 这确实需要我导出并重新导入所有数据,以便我可以重建表,但是,对于其他找到此帖子的人来说,这可能不是一个很好的解决方案,除非他们手动更改表的身份。

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

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