-->
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.  [ 10 posts ] 
Author Message
 Post subject: Getting all loaded/changed objects of a session
PostPosted: Wed Mar 15, 2006 4:19 am 
Newbie

Joined: Mon Jan 30, 2006 9:15 am
Posts: 11
Hello, is there any possibility to get all objects associated with a session
or is there even a method to get all changed objects within a session?

Thx, thomas


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 16, 2006 2:46 am 
Newbie

Joined: Mon Jan 30, 2006 9:15 am
Posts: 11
I would be very appreciate, if anyone has a answer for my question...

Regards
Thomas


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 16, 2006 11:17 am 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
The only place I've seen this list exposed is in the collection passed to IInterceptor.PreFlush() and PostFlush(). We track the dirty and transient status on our entities ourselves, so we actually go through the session's cache there.

Unfortunately, that's not very useful if you want to get at the session cache at any other time. Why isn't this exposed? I would have expected something like this on the Session object:
Code:
public ICollection Entities {get ;} // readonly collection

public bool IsDirty(object entity);

public bool IsTransient(object entity);


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 17, 2006 2:58 am 
Newbie

Joined: Mon Jan 30, 2006 9:15 am
Posts: 11
Nels_P_Olsen wrote:
I would have expected something like this on the Session object:
Code:
public ICollection Entities {get ;} // readonly collection

public bool IsDirty(object entity);

public bool IsTransient(object entity);




Thx for your comments ... this properties/methods would be nice...
Is it possible to extend the Session with somethink like that, or has it some technical drawbacks which I don't know?

Thank you,
Thomas


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 17, 2006 3:57 am 
Newbie

Joined: Mon Jan 30, 2006 9:15 am
Posts: 11
I have just checked the order of IInterceptor method calls:

I'm a little bit confused ...:

The order of called interceptor methods is:
OnSave
PreFlush (is called AFTER the insert statement(!))
PostFlush

In my opinion the PreFlush should be fired before the insert statement is executed!

Can someone explain this behaviour..?

Regards, Thomas


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 17, 2006 11:58 am 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
I think the SQL insert/update statements don't get generated until after PreFlush(). We gave up on trying to use OnSave(), and put our logic in PreFlush() instead. We loop through the entire collection of entities in the session cache, and since our entities all implement an interface where they track their own dirty and transient status, we can tell which entities need consideration.

In particular, during PreFlush() we set a LastUpdatedDate property on dirty entities. We can't do this during OnSave() because we're using dynamic-update, which causes only changed properties to appear in the object[] state array passed in. Besides, the signature to OnSave() is horrible, since it forces you to manipulate properties using 3 separate arrays -- state, propertyNames and types. It would be much cleaner (and more compatible with an independent method that knows about entities or entity interfaces) to simply modify the entity passed in. We can do that in PreFlush().


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 20, 2007 1:18 am 
Beginner
Beginner

Joined: Thu Nov 02, 2006 5:11 pm
Posts: 32
Location: Toronto
Is there a definitive answer to this? I need a way of finding all dirty entities in the session without actually writing anything to the database. If I call Flush(), I could use IInterceptor.OnFlushDirty to build up a list of all dirty entities, but at that point it seems too late to prevent NHibernate from actually writing out the updates to the DB.

Any thoughts appreciated.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 20, 2007 10:00 am 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
Another use for getting the list of all entities in the session (dirty or not) is to deal with removing associations when deleting an entity, to avoid the "ObjectDeletedException: deleted entity would be re-saved by cascade (remove from associations)" exception. The code requesting the delete ususally doesn't know what all the possible interfering associations are for child entities deleted through cascades, and certainly has no idea what the other objects are in the session cache (unless you create a separate session just for the delete, or flush and clear the session just before the delete). It might be possible to loop through the entities in the session cache and use reflection to find and remove these other associations ...


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 19, 2007 1:07 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
A lame but possible solution to this, assuming you create all your entities through a factory, is to have that factory keep a WeakReference collection of every entity it creates. Then the factory can provide a method like
Code:
object[] GetEntitiesInSession(ISession session)

The method would loop through all weak references (removing dead references as it finds them) call session.Contains() on them, and add them to the resulting list appropriately ...


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 19, 2007 5:19 pm 
Expert
Expert

Joined: Tue Aug 23, 2005 5:52 am
Posts: 335
The inserts you're probably seeing before flush are the inserts used to get the id of your entities if you have used a database generated id. This is unavoidable unless you use NHibernate generated or assigned ids.

Normally if you want to ensure updates aren't persisted in the database unless a specific action has occurred is to use a transaction and only to commit it explicitly - if the action required does not occur then roll it back.

This may not meet your specific needs, but should answer the question of why you're seeing inserts before a flush.

Cheers,

Symon.


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