-->
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: Problem Deleting Detached-Collection
PostPosted: Fri Jun 29, 2007 1:29 pm 
Beginner
Beginner

Joined: Wed May 02, 2007 12:24 am
Posts: 41
Hello,

I'm having an issue, and I'm not sure if it is an issue or expected behavior. I'v simplified it for the sake of this post:

When it works:
I've a class Cat that has a list of Kittens. When I load the cat from the db and remove a kitten from the list and call SaveOrUpdate the kitten is removed from the db. As expected!

When it doesn't work:
When I load the cat from teh db and remove the kitten. Then clone the Kittens list and call SaveOrUpdate the kitten is NOT removed from the db.

Unfortunately, I'm forced to clone the list. Is this an expected behavior for nhibernate? Or am I perhaps doing something else that's cuasing it to behave this way.

Thanks

Here is a code snippet:

class Cat
{
IList<Cat> kittens;
..
}

Cat cat = GetCatFromDB(catId);
cat.kittens.RemoveAt(0);

IList<Cat> newKittens = new List<Cat>();
foreach (Cat c in cat.kittens)
newKittens.Add(c);
cat.kittens = newKittens;

SaveOrUpdateObject(cat); //the kitten is not removed


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 29, 2007 1:57 pm 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Please see http://www.hibernate.org/Documentation/NHibernateTroubleshootingGuide, I have just added a section there describing your likely problem (you are not calling Flush nor committing a transaction).


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 29, 2007 2:32 pm 
Beginner
Beginner

Joined: Wed May 02, 2007 12:24 am
Posts: 41
Thank for the quick response.

However, Sergey as you can see in the post, everything works fine when I don't switch the collection.

Could you please tell me if switching the collection would cause the problem I'm experiencing.

THanks


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 29, 2007 2:59 pm 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
It might depend on a whole host of other things - are you using inverse="true" in your mappings? Are you using "identity" identifier generation strategy? So fix that Flush/Commit issue if you haven't already, and if the problem doesn't go away then post your mappings.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 29, 2007 3:34 pm 
Beginner
Beginner

Joined: Wed May 02, 2007 12:24 am
Posts: 41
Hello Sergey,

THanks again for quick response.

I have read your document. It is a fine document and thank you for making it available.

However, it doesn't solve my problem. I do have inverse = true.

Please note that, I can delete from a detached collection, and everything works fine. It gets deleted from the db as expected.

But when I clone the collection and try to save then it doesn't delete from the db any more (however, insert, update still work). If I had problem with flush/transaction none of these scenarios would work, no?

I will need to spend some time to come up with a mapping and I'll post it. I was just wondering this may provide you with enough information.

So the sample bellow would stop working:

class Cat
{
IList<Cat> kittens;
..
}

Cat cat = MyHelper.GetCatFromDB(catId);
cat.kittens.RemoveAt(0);

//region CLONE THE KITTENS
IList<Cat> newKittens = new List<Cat>();
foreach (Cat c in cat.kittens)
newKittens.Add(c);
cat.kittens = newKittens;
//endregion

MyHelper.SaveOrUpdateObject(cat); //the kitten is not removed


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jun 30, 2007 1:52 pm 
Regular
Regular

Joined: Wed Apr 25, 2007 4:18 am
Posts: 51
Location: Belarus, Gomel
Hi h1!

First of all what "cascade" setting do you have for <bag> of kittens in your mapping? Is it all-delete-orphans or not?

Then I don't think it is possible for NHibernate to track deletion in "plain" List<Cat>.
NHibernate use special "Persistent collections" - PersistentGenericBag<T> in case of generic bags - and it tracks "initial collection state" (aka collection snapshot) there, so it can compare this snapshot with current state of collection to track changes.
And AFAIK it is prohibited to "switch" Persistent collections if you use cascade="...-delete-orphans" for them - so you must have error in that case
You may not dereference a collection with cascade="all-delete-orphan"

Why does it work for updates? There IS child object in collection and there IS it's state in session cache - so while doing cascade operation NHibernate see that object was modified and it saves it.
Why does it work for insertions? I think "unsaved-value" for Cat is the key - There IS child object in collection and it's Id value tell NHibernate that it is "new" object - so it saves it as well.
Why it doesn't work for deletion? There is NO object in collection and collection itself have NO snapshot - so this object is not processed while doing cascade operation.

Assume that you want to move some kitten from one parent to another - it will be deleted from one collection and inserted into another - but what SQL do you expect then? There must be single Update (that will change ParentId for affected Cat record), but not Delete+Insert.
Another example - many-to-many logical relation (for example if you'll track both kitten parents - male cat and female cat) kitten record must not be deleted if you remove it from just one collection! Moreover you can't use cascade delete in this case - so you have to do explicit session.Delete(someKitten) in you really want to delete kitten from DB.

_________________
WBR, Igor


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 10, 2007 1:02 am 
Beginner
Beginner

Joined: Wed May 02, 2007 12:24 am
Posts: 41
Thanks Igor,

But if this is true, then it is real bad news for me.

You see I'm in a client/server world. When the object gets to the client it is materialized as a List, not PersistentGenericBag.

What if I mark the kittens as deleted (by setting a status) then on the server delete them from the db?

Is that a good work-around...is there a better work around?

Thanks


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.