These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: Insert/Update issue when using an IUserType
PostPosted: Thu Jul 06, 2006 4:42 am 
Newbie

Joined: Wed Jun 28, 2006 8:08 am
Posts: 5
Hi.

I have some problems when using an IUserType. When I insert an entity NHibernate first executes an insert-statement and then an update-statement. If I do not use an IUserType it just executes an insert-statement as expected.

I have made a small example to reproduce the problem.

NHibernate version:

1.2.0.1001

Mapping documents:

Code:
  <class name="TestClass" table="TestClass" lazy="false">

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

    <property name="Description" type="NHibernateDataMapper.Test.TestEnumType, NHibernateDataMapper">
      <column name="description" />
    </property>     
 
  </class>


The SQL (SQL Server 2000) to create the table:

Code:
CREATE TABLE TESTCLASS
(
  id numeric,
  description varchar,
)


And here is the source code:

Code:
public enum TestEnum
{
   AValue,
   BValue
}

public class TestClass
{
   public int id;
   public TestEnum description;            

   public int Id
   {
      get { return id; }
      set { id = value; }
   }

   public TestEnum Description
   {
      get { return description; }
      set { description = value; }
   }
}

public class TestEnumType : IUserType
{
   public bool Equals(object x, object y)
   {
      return x == y;
   }

   public object NullSafeGet(IDataReader rs, string[] names, object owner)
   {
      string value = (string)rs[rs.GetOrdinal(names[0])];

      if (value == "A")
      {
         return TestEnum.AValue;
      }

      if (value == "B")
      {
         return TestEnum.BValue;
      }

      throw new ArgumentException("Cannot map value");
   }

   public void NullSafeSet(IDbCommand cmd, object value, int index)
   {
      IDataParameter par = (IDataParameter)cmd.Parameters[index];

      switch ((TestEnum)value)
      {
         case TestEnum.AValue:
            par.Value = "A";
            break;
         case TestEnum.BValue:
            par.Value = "B";
            break;
      }
   }

   public object DeepCopy(object value)
   {
      return value;
   }

   public SqlType[] SqlTypes
   {
      get { return new SqlType[] { new StringSqlType() }; }
   }

   public Type ReturnedType
   {
      get { return typeof(TestEnum); }
   }

   public bool IsMutable
   {
      get { return false; }
   }
}


When I try to insert a TestClass instance using code like this:

Code:
...
TestClass testClass = new TestClass();
testClass.Id = 1;
testClass.Description = TestEnum.AValue;
session.Save(testClass);


an insert is done, but it is always followed by an update. If I change the TestClass to use a simple string instead of the enum, only an insert is generated. Is this a bug in NHibernate or is something wrong with my IUserType implementation?

I have also tried to make an IUserType which just maps a string to itself. Here things work too (just one insert). So I suppose it might have something to do with the enum?

Thanks in advance,
Jacob Ilsø

P.S. I have attached an excerpt of the log file in case this helps:

Code:
3093 [4868] DEBUG NHibernate.Impl.SessionImpl (null) - opened session
3124 [4868] DEBUG NHibernate.Transaction.AdoTransaction (null) - begin
3140 [4868] DEBUG NHibernate.Connection.DriverConnectionProvider (null) - Obtaining IDbConnection from Driver
3546 [4868] DEBUG NHibernate.Impl.SessionImpl (null) - generated identifier: 1
3578 [4868] DEBUG NHibernate.Impl.SessionImpl (null) - saving [NHibernateDataMapper.Test.TestClass#1]
3609 [4868] DEBUG NHibernate.Transaction.AdoTransaction (null) - commit
3640 [4868] DEBUG NHibernate.Impl.SessionImpl (null) - flushing session
3656 [4868] DEBUG NHibernate.Impl.SessionImpl (null) - Flushing entities and processing referenced collections
3687 [4868] DEBUG NHibernate.Persister.Entity.AbstractEntityPersister (null) - NHibernateDataMapper.Test.TestClass.Description is dirty
3703 [4868] DEBUG NHibernate.Impl.SessionImpl (null) - Updating entity: [NHibernateDataMapper.Test.TestClass#1]
3718 [4868] DEBUG NHibernate.Impl.SessionImpl (null) - Processing unreferenced collections
3749 [4868] DEBUG NHibernate.Impl.SessionImpl (null) - scheduling collection removes/(re)creates/updates
3749 [4868] DEBUG NHibernate.Impl.SessionImpl (null) - Flushed: 1 insertions, 1 updates, 0 deletions to 1 objects
3781 [4868] DEBUG NHibernate.Impl.SessionImpl (null) - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
3812 [4868] DEBUG NHibernate.Impl.Printer (null) - listing entities:
3828 [4868] DEBUG NHibernate.Impl.Printer (null) - NHibernateDataMapper.Test.TestClass{Description=AValue, Id=1}
3843 [4868] DEBUG NHibernate.Impl.SessionImpl (null) - executing flush
3874 [4868] DEBUG NHibernate.Persister.Entity.SingleTableEntityPersister (null) - Inserting entity: [NHibernateDataMapper.Test.TestClass#1]
3921 [4868] DEBUG NHibernate.Impl.BatcherImpl (null) - Opened new IDbCommand, open IDbCommands :1
3937 [4868] DEBUG NHibernate.Impl.BatcherImpl (null) - Building an IDbCommand object for the SqlString: INSERT INTO TestClass (description, id) VALUES (:description, :id)
3953 [4868] DEBUG NHibernate.Persister.Entity.SingleTableEntityPersister (null) - Dehydrating entity: [NHibernateDataMapper.Test.TestClass#1]
3968 [4868] DEBUG NHibernate.Type.Int32Type (null) - binding '1' to parameter: 1
3999 [4868] DEBUG NHibernate.SQL (null) - INSERT INTO TestClass (description, id) VALUES (@p0, @p1)
4015 [4868] DEBUG NHibernate.SQL (null) - @p0 = 'A'
4031 [4868] DEBUG NHibernate.SQL (null) - @p1 = '1'
4140 [4868] DEBUG NHibernate.Impl.BatcherImpl (null) - Closed IDbCommand, open IDbCommands :0
4156 [4868] DEBUG NHibernate.Persister.Entity.SingleTableEntityPersister (null) - Updating entity: [NHibernateDataMapper.Test.TestClass#1]
4187 [4868] DEBUG NHibernate.Impl.BatcherImpl (null) - Opened new IDbCommand, open IDbCommands :1
4218 [4868] DEBUG NHibernate.Impl.BatcherImpl (null) - Building an IDbCommand object for the SqlString: UPDATE TestClass SET description = :description WHERE id = :id
4234 [4868] DEBUG NHibernate.Persister.Entity.SingleTableEntityPersister (null) - Dehydrating entity: [NHibernateDataMapper.Test.TestClass#1]
4249 [4868] DEBUG NHibernate.Type.Int32Type (null) - binding '1' to parameter: 1
4281 [4868] DEBUG NHibernate.SQL (null) - UPDATE TestClass SET description = @p0 WHERE id = @p1
4296 [4868] DEBUG NHibernate.SQL (null) - @p0 = 'A'
4312 [4868] DEBUG NHibernate.SQL (null) - @p1 = '1'
4328 [4868] DEBUG NHibernate.Impl.BatcherImpl (null) - Closed IDbCommand, open IDbCommands :0
4359 [4868] DEBUG NHibernate.Impl.SessionImpl (null) - post flush
4374 [4868] DEBUG NHibernate.Impl.SessionImpl (null) - transaction completion
4390 [4868] DEBUG NHibernate.Transaction.AdoTransaction (null) - running AdoTransaction.Dispose()
4406 [4868] DEBUG NHibernate.Impl.SessionImpl (null) - closing session
4421 [4868] DEBUG NHibernate.Impl.SessionImpl (null) - disconnecting session
4453 [4868] DEBUG NHibernate.Connection.ConnectionProvider (null) - Closing connection
4484 [4868] DEBUG NHibernate.Impl.SessionImpl (null) - transaction completion


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 06, 2006 6:31 am 
Newbie

Joined: Wed Jun 28, 2006 8:08 am
Posts: 5
Hi.

I have found the solution. In the Equals method == does not work.

It must be written like this:

Code:
public bool Equals(object x, object y)
{
   return x.Equals(y);            
}


I thought == would work since enums are value types, but apparently not so...

/Jacob


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.