1

I've been looking all over and can't find a good answer to this problem with NHibernate.

I'm working with an API that uses NHibernate. I'm doing a data transfer and I'm trying to use their User object to save user data.

I create the object

User objUser = new User();

They have a mapping file that specifies ids be set to identity

<id name="Id" column="UserId" type="int">
  <generator class="native" />
</id>

but one of my requirements is to save the old id to the user table. I need to be able to temporarily set the identity insert to ON and save the record but still be able to use the User object to save the associated data.

I tried doing something like this

 using (ISession session = MyDatabaseFactory.SessionFactory.OpenSession())
{
    using (ITransaction trans = session.BeginTransaction())
    {
       session.CreateSQLQuery("SET IDENTITY_INSERT Users  ON").UniqueResult();
       session.Save(objUser, objUser.Id);
       session.Flush();

       trans.Commit();

       session.CreateSQLQuery("SET IDENTITY_INSERT Users OFF").UniqueResult();

       session.Close();
       objUser= session1.Merge(objUser);
       }
 }

but when trying to save the user object again later like this

objUser.Passwords.Add("password1");
                    objUser.Save()

I get an error: a different object with the same identifier value was already associated with the session

user204588
  • 1,613
  • 4
  • 31
  • 50
  • This looks like a case when the Identity Seed is less than the current identity. i.e the seed is 0 for the next Id to be 1, but you've already inserted 1 and not set the seed to 1. – Phill Apr 22 '13 at 09:02

2 Answers2

0

Save() tries to insert a new object to the database. You should try Update(), which updates an existing record in the database for a persistent object. You can also use SaveOrUpdate() which decides which of the above is to be used.

By calling Save() again, I think it is trying to insert another record with the same Id. The answer here has more details.

Community
  • 1
  • 1
mridula
  • 3,203
  • 3
  • 32
  • 55
0

If your requirement is just for a very special case, e.g. database update or migration, you could probably work with a different session factory, where the ID is assigend:

<id name="Id" column="UserId" type="int">
  <generator class="assigned" />
</id>

And assign the id:

User objUser = new User() { UserId = 42 };

If your case is tightly integrated in normal business cases, this is not a very good solution.

You may try to implement your own IIdentifierGenerator. Don't expect it to be simple and straight forward. You may have a chance when you derive the IdentityGenerator, merge some code from the Assigned generator and hack this SET IDENTITY_INSERT Users ON stuff into it ... The generator needs to know when to use which strategy. E.g. when the id is still 0, let SQL Server create one, when it is something else, insert the assigned value.

Stefan Steinegger
  • 63,782
  • 15
  • 129
  • 193