-->
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.  [ 9 posts ] 
Author Message
 Post subject: Circular Object Reference (cache)
PostPosted: Mon Jul 21, 2008 2:57 am 
Newbie

Joined: Mon Jul 21, 2008 2:52 am
Posts: 8
I have a user table as follows
Code:
create table usr
(
UsrId int,
UsrCode varchar(8),
UpdatedBy int
)

with data

UsrId       UsrCode    UpdatedBy
----------- ---------- -----------
1           tusr1      1
2           tusr2      1


C# code
public class Usr
{
   protected int _usrId;
   protected string _usrCode;
   protected Usr _updatedBy;

   public virtual int Id
   {
      get {return _id;}
      set {_id = value;}
   }

   public virtual string UsrCode
   {
      get { return _usrCode; }
      set { _usrCode = value; }
   }

   public virtual Usr UpdatedBy
   {
      get { return _updatedBy; }
      set { _updatedBy = value; }
   }

}

Nhibernate.hbm

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
   <class name="Test.Usr, Test" table="Usr">
      <id name="Id" type="Int32" unsaved-value="null">
         <column name="UsrId" length="4" sql-type="int" not-null="true" unique="true" index="PK_Usr"/>
         <generator class="increment"/>
      </id>
      <property name="UsrCode" type="String">
         <column name="UsrCode" length="10" sql-type="varchar" not-null="true"/>
      </property>
      <many-to-one name="UpdatedBy" class="Test.Usr, Test" lazy="false">
         <column name="UpdatedBy" length="4" sql-type="int" not-null="false"/>
      </many-to-one>
   </class>
</hibernate-mapping>


Problem when I am modifying RequestedBy, the main class is also update. For example

Usr usr = session.Get<Usr>(1);

usr.UpdatedBy.Id = 2; <===== At this line, usr.Id is also updated to 2. It looks usr and UpdatedBy is pointing to the same Usr object (due to NHibernate caching?).

How can I tell NHibernate not to use cache? I've tried Evict(typeof(Usr)) after Get but it's too late. Should I explore IInterceptor? If yes any hint?

Thanks.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 21, 2008 4:00 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
Since you have an association to another object here, you can't change it by simly setting another id to the object. You have to replace the whole object:

usr.UpdatedBy = usr2;

As an alternative, you can just map the id of the user instead of the whole object. Then your approach would work.

_________________
--Wolfgang


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 21, 2008 8:50 am 
Newbie

Joined: Mon Jul 21, 2008 2:52 am
Posts: 8
Thanks for your prompt reply.

However, the problem is that on this statement usr.UpdatedBy = usr2. It seems that NHibernate using the cached usr for both usr and usr.UpdatedBy objects since they both are usr.Id = 1.

How do I clear the cache or tell NHibernate to create a new usr object for UpdatedBy even though the id is the same?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 21, 2008 9:04 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
You can't have more than one object with the same id ! It's the primary key. From what you have described, it doesn't sound like a caching problem. Can you describe what you want to achieve in more detail ?

_________________
--Wolfgang


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 21, 2008 8:28 pm 
Newbie

Joined: Mon Jul 21, 2008 2:52 am
Posts: 8
Hi Here is the picture representation of the problem.

Code:
Retrieve Process for usr.id =1 with data as per first post

UsrId    UsrCode  UpdatedBy
1         tuser1     1

  Populate Usr
+------------------+       +------------------+
|                  |       |                  |
|  usr.Id = 1      | <---- |      usr         |
|   (Cached)       |       |                  |
|                  |       |                  |
+------------------+       +------------------+

  Populate UpdatedBy

+------------------+       +------------------+
|                  |       |                  |
|  usr.Id = 1      | <---- |      usr         |
|   (Cached)       |       |                  |
|                  |       |                  |
+------------------+       +------------------+
               ^             /
               |            /
               \           /
                \         V
        +------------------+
        |                  |
        |   UpdatedBy      |
        |                  |
        |                  |
        +------------------+


Nhibernate cache noticed that usr and UpdatedBy is the same record and reuse the cached Usr object. As the result, when I change UpdatedBy.Id to 2, usr.Id is also changed to 2 as they usr and UpdatedBy are pointing to the same object.

I want This to happen

Code:

  Populate Usr
+------------------+       +------------------+
|                  |       |                  |
|  usr.Id = 1      | <---- |      usr         |
|                  |       |                  |
|                  |       |                  |
+------------------+       +------------------+


  Populate UpdatedBy


+------------------+       +------------------+
|                  |       |                  |
|  usr.Id = 1      | <---- |      usr         |
|                  |       |                  |
|                  |       |                  |
+------------------+       +------------------+
                                 |
                                 |
                                 |
                                 v
+------------------+      +------------------+
|                  |       |                  |
|  usr.Id = 1      | <---- |    UpdatedBy     |
|                  |       |                  |
|                  |       |                  |
+------------------+       +------------------+

When I change UpdatedBy.Id to 2, usr.Id won’t be changed to 2 as they are 2 different objects.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 22, 2008 2:02 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
This is no caching problem. Hibernate is about objects, not values. Changing the id of an persisted object is not the same like changing the reference.

If you want to assign a different usr to UpdatedBy, you have to assign a different usr object, either by creating a new one (with id 2) or loading it from the database.

Code:
Usr usr1 = session.Get<Usr>(1);
Usr usr2 = session.Get<Usr>(2); // or usr2 = new Usr(2);

usr1.UpdatedBy = usr2;


I assume you want UpdatedBy to be set to the current user to provide some kind of change information. I furthermore assume that you have the id or the current user available through some "manager" class. So at the end your code would look like this:

Code:
usr1.UpdatedBy = usrMgr.CurrentUsr;


I hope that makes it clearer.

_________________
--Wolfgang


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 22, 2008 7:51 pm 
Newbie

Joined: Mon Jul 21, 2008 2:52 am
Posts: 8
Hi Wolli,

Thanks for your effort to help me. I've tried your suggestion and still having the problem. Could you use my code and try it (if you have the time) then you'll have a better picture of my problem.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 23, 2008 2:55 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
Can you post the code of your last try ? Everthing that happens between opening the session and closing the session.

_________________
--Wolfgang


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 24, 2008 9:21 pm 
Newbie

Joined: Mon Jul 21, 2008 2:52 am
Posts: 8
Hi Wolli,

I've tried again using your suggestion

usr.UpdatedBy = usr2;

instead of
usr.UpdatedBy.id = usr2.id;

It's working now. I must have done something wrong.

Thanks for your help.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 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.