-->
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.  [ 7 posts ] 
Author Message
 Post subject: Dirty object does not get updated...
PostPosted: Sun Nov 13, 2005 7:00 am 
Regular
Regular

Joined: Mon Aug 29, 2005 3:07 pm
Posts: 77
I'm learning NHibernate, and I've been playing around with it a bit this weekend.

I've managed to get objects out of the database, insert new objects into the database, etc...
However, now I just want to update an existing object, and NHibernate doesn't seem to co-operate, or I'm doing something wrong (I think the latter will probably be the problem :P )

I've this code:
Code:
ISession sess = sessionFactory.OpenSession();
HibTestDomain.Container c = (HibTestDomain.Container)sess.Get(typeof(HibTestDomain.Container), 20);

c.Name = "bliep";

sess.SaveOrUpdate (c);

sess.Close();


Now, I would think that this code should get the Container with primary id 20 out of the database: this works fine, I can see the select statement has been executed in Sql Server Profiler.

Then however, I see no update statement to update the name of my object. :?
When I look in the DB, my 'container' still has his old name.

However, when I do this:
Code:
ISession sess = sessionFactory.OpenSession();
Container c = new Container();
c.Name = "bliep";
sess.Save (c);

Then, a new object is insertd in the DB...

What am I doing wrong here ?[/code]


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 13, 2005 8:09 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Wrap it all in a transaction (session.BeginTransaction) and the updates will happen on commit.

Longer answer: Updates only happen when you flush a session, this is done on commit, or you can manually flush the session by calling session.Flush, but this is not recommended, use transactions. Objects that use identity identifier generator are saved immediately, but this is an exception.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 13, 2005 9:40 am 
Regular
Regular

Joined: Mon Aug 29, 2005 3:07 pm
Posts: 77
Normally, i'd use transactions but since this was just a test, I didn't wrap it all up in a transaction.

Flushing the session or putting my Save operation in a transaction indeed did the trick.

However, now I see that instead of just one update statement, 3 update statements are issued.
(My object has a name, which i've changed, but it also contains a collection that contains 2 other objects. An update statement is also issued for these 2 objects, but I haven't changed anything to these 2 objects. :?

However, in an other situation this does not occur.... I'll investigate why Nhibernate marks these objects as dirty.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 13, 2005 11:50 am 
Regular
Regular

Joined: Mon Aug 29, 2005 3:07 pm
Posts: 77
Ok, I discovered that these objects get updated, because I save them in another session then the session in where I've loaded it...
Then, the object is considered as dirty.

However, in a Windows application, I cannot keep that session open for such an amount of time ? I mean, I don't think it is recommended to open a session when you open the form, and keep it open until you close that form ?


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 13, 2005 1:21 pm 
Regular
Regular

Joined: Mon Aug 29, 2005 3:07 pm
Posts: 77
I've solved this by using a long lived session...

In the method that is responsible of showing my form, I've this code
Code:
public void Execute( int id )
{
   // _session is a member variable of the form.
   _session = Appsettings.Instance.SessionFactoryObj.OpenSession();

   _container c = (Container)_session.Get(typeof(Container), id);

   _session.Disconnect();

   this.Show();
}


Then,when the user clicks ok to close to form and confirm any changes he's made, this code is executed:
Code:
public void OkButtonClick()
{
    if( _session.IsConnected == false )
    {
       _session.Reconnect();
    }

    _session.SaveOrUpdate (_container);
    _session.Flush();
    _session.Close();
    this.Close();
}


(I know that this code is not very good, but it's just some test-code to get familiar with hibernate).

However, what about this approach ? Is it a good one ? What about the disadvantages of keeping the session object as long lived as the lifetime of the form (the form is just some kind of 'detail-form' where the user can see and edit information about one object (container in this case).

I've also read about detached objects. I've tried this as well (create a session in where I'll load the object, close the session; when the user wants to save its changes, create a new session, attach the object to the session (by using session.lock ), and then call SaveOrUpdate, but this doesn't seem to work very well...
Nothing gets updated, even though I've changed some things. Debugging learned me that the re-attached object contains the same values as the object that i wanted to update (I'm using .NET databinding).

When I do not make use of .NET databinding, then, it works as expected:
Code:
public void OkButtonClick()
{
    ISession s = SessionFactoryObj.OpenSession();
    s.Lock (_container, LockMode.None);
    _container.Name = txtName.Text;
    s.SaveOrUpdate (_container);
    .....
}


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 15, 2005 3:49 pm 
Regular
Regular

Joined: Mon Aug 29, 2005 3:07 pm
Posts: 77
Is there any way how i can get this to work without using a 'long lived session' ?

I've tried to do this:

- get the object, close the session, databind the properties of the object to the controls.

- then, when the user wants to saves his changes, open a new session, save the object using this new session.

Now, since I save this object using a new session, NHibernate says: everything of this object is dirty, so, i've to update everything. However, in my case this is not true. The related records in the related table are not changed, so , they should not have been updated.
I've also tried to put the object in the session first, before calling 'SaveOrUpdate', but, since i'm using databinding, the object is put in the session with the changes... So, when i call update, NHibernate doesn't see any changes, and nothing gets updated.
I've also tried to 'lock' a clone of my original object in the session, but, when I call Update, then NHibernate throws an exception saying that there's already an object with the same id in this session.
(When I do not use databinding, it works like a charm (getting the object in the session via lock, persisting the changes in my object, and then persisting the changes in the object in the DB).

So, is the only solution for this problem:
- using a long lived session
or
- not using databinding ?

Is the combination not possible ?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 17, 2005 11:36 am 
Contributor
Contributor

Joined: Thu May 12, 2005 9:45 am
Posts: 593
Location: nhibernate.org
If you correctly set up lazy loading and cascading, saving the whole object graph shouldn't be really annoying.

Anyway, you may use the session-per-conversation pattern; read Implementing long Conversations... (it is similar to what you are doing)

_________________
Pierre Henri Kuaté.
Get NHibernate in Action Now!


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