I have an entity (the "parent") which contains a dictionary with unidirection one-to-many references to instances of a "child" entities. The HBM file for the parent contains the following attributes for the map tag: cascade="all-delete-orphan" inverse="false".
An instance of the parent is persisted to the database, then retrieved and a new child instance added to the parent instance dictionary. When the transaction for this update is committed I've noticed that the OnPreInsert method is fired on a registered instance of IPreInsertEventListener, with the child instance being inside the Entity property of the PreInsertEvent instance passed in.
Is there any way I can find a reference to the parent class in the listener when this dictionary insert is committed? I've tried to register a IPreCollectionUpdateEventListener and this doesn't pick anything up.
As I've said, this is a unidirectionary relationship, and I know that I could achieve what I want by making it bidirectional, but this is something that I'd rather not do.
One option would be to register a IPreUpdateEventListener instance as well.
In this case, you could trap the parent object instead and iterate its children to do your stuff.
Related
Suppose Object A contains a collection of Object B. Let's say it's a one to many (an object B belongs to only one object A)
Now suppose for some reason I already have all the different Object B's in the session cache already.
Now if I went and fetched an object A from the database (giving me an object A with an uninitalized collection of Object B), is there a way I can tell nhibernate to go into the session cache and find all the object B's that belong to this object A and initialize the collection of object B's within the object A I just got?
By initializing the collection, I mean that when I try to use it, it does not need to send any more queries to the database.
I'm using Nhibernate 3.2.
Thanks!
Short answer: no. It doesn't work that way.
Just wondering what's the best-practice for saving a Parent that ordinarily contains a collection of Child objects (many-to-many in my case), but that collection in the Parent is currently set to null because it hasn't been loaded?
In my case, the Parent is passed to my service layer from a Web page. The web page has only populated the Parent's simple attributes from a form.
I know there are several Child objects linked to the Parent in the database, but the 'children' property is currently null.
If I save the Parent, even though my of Children is set to cascade="none", when I save Parent, all the links are deleted (I can even see the delete statements NHibernate issues in the logs).
I can think of several ways to solve this:
1) Load the children seperately and then set the Parent's child collection to them and then save the parent (works but this is an additional trip to the database).
2) Issue an update on ONLY the simple properties using HQL or Native SQL.
Update: I'm not sure my cascade behaviour is working properly actually. From the docs, it suggests that NHibernate won't mess with my collection unless cascade is set to save-update, all-delete-orphan etc. But this is my mapping
(from Order.hbm.xml)
<bag name="OrderItems" table="order_item" cascade="none" lazy="true">
<key column ="order_id" />
<many-to-many class="MenuItem" column="item_id"/>
</bag>
When Order.OrderItems is null, and I save my Order object using SaveOrUpdate(Order), it definately deletes the collection. I want them to be preserved. Is my configuration wrong or something?
Thanks
I wouldn't actually use the real Parent object for passing data from UI to the service layer. You could instead implement a lightweight class (Data transfer object) that would contain just those basic properties and then pass it to the service tier and populate (either manually or using AutoMapper) the parent's properties.
I have parent+child relationship and child collection is mapped as lazy. I fetch a parent, and of course because of the lazy loading child collection is not loaded. But when I want to update my parent NH first loads child collection. I'm interesting is this by default, or I went wrong somewhere. Collection is lazy, inverse=true and cascade="all-delete-orphan". I assume that because of cascade mapping NH wants to check changes on the child collection and it is accessed for the first time so lazy load did it's job. Please can somebody confirm this.
When updating the parent object NHibernate should not have to load the child collection unless you are modifying the foreign key relationship column.
Inverse="true"
This means that the objects in the child collection are responsible for managing the relationship with the parent.
cascade="all-delete-orphan"
When adding a new child object to the collection it will cascade to the DB without you having to explicitly call Session.Save(childobj) first. It also means if you delete the parent object all of the child collection object will also be deleted from the DB.
I use those exact settings for my child collection relationships and do not see this behaviour.
Could you post your mappings/fluent maps/test code which may give more insight into the issue at hand?
What is the difference between SaveOrUpdateCopy and SaveOrUpdate method in NHibernate?
From nHibernate doc:
Copy the state of the given object
onto the persistent object with the
same identifier. If there is no
persistent instance currently
associated with the session, it will
be loaded. Return the persistent
instance. If the given instance is
unsaved or does not exist in the
database, save it and return it as a
newly persistent instance. Otherwise,
the given instance does not become
associated with the session.
There is one nice blog post on the subject.
I have a parent class that contains a list of children. I have the parent and child mapped bidirectional with a has-many and an inverse on the parent with cascade.all turned on. If I modify an object in the child list, but no property on the parent, nHibernate does not save the child. If I modify a property on the parent everything saves fine. Is this by design or is there a special property I need to set?
This might have something to do with the way you are adding the children to the collection. In a bidirectional, you have to manage both sides of the relationship in the code. Consider the example from the Fluent Nhibernate Getting Started Guide. Check the Store Entity.
A Store has many Employees. The Staff property of Store is collection of Employees. The relationship is setup as bidirectional.
Store has the following method
public virtual void AddEmployee(Employee employee)
{
employee.Store = this;
Staff.Add(employee);
}
As you can see, the childs Parent property needs to be set to the parent object. If this is not done, then Nhibernate will not be able understand who the parent of the child is and cannot automatically save the child if only the child is modified and the SaveOrUpdate(parent) is called.
You need to do both.
I figured it out. I was testing auditing using various listners. When I attached to the IFlushEntityListner it caused saves to stop working. Geez that was frustrating. Thanks everyone!