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!
Related
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.
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?
In my application I need to save with NHibernate entities received from WCF service.
Currently I'm using session SaveOrUpdate method for this purpose.
Often we don't need to edit reference properties, so from client I receive object, which has empty collections. But I don't want this empty collection to reflect in database.
Example:
public class Product
{
public virtual string Name {get;set;}
public virtual IList<Stores> Stores {get;set;} <--- Stores is empty, but should not be cleared in databse.
}
Thanks,
Oksana.
As far as I understand it, you want to update certain properties of the object if it already exsits, and no touch others, is that correct?
Well, basically, in such a case what you'd need to do is this:
establish an NHiberate session
based on some ID, load the current state of the object from the database
update those properties you want to update from the entity you've received in your service call
save the modified object back
With this approach, you'll only update those properties you want, and everything else is being left alone.
Does that seem like an approach you can work with?
Marc
I'm not sure to understand the question. If you are new to NHibernate have a look at the documentation with the term cascade. This defines what is persisted when an object containing others has to be saved.
I am using Nhibernate but still i am confused about (lazy-loading and Eagerly loading) these two topics due to poor understanding of Nhibernate.
Please define me lazy-loading and Eagerly loading in simple words.
Also why we use castle.Dynamic Proxy ?
Lazy loading and eager loading are concepts that must be present in every ORM.
Let's take a parent-child relation:
class Parent {
String name;
List<Child> childs;
}
class Child {
String name;
}
When you load an element of Parent, the ORM must decide if it loads the childs collection also (through a join for example) or if it delays the query to load the childs until you actually access the collection
parent.childs.get(0)
When you load the childs collection ahead, ie, before accessing the collection, it is eagerly loading because you are expecting to access the childs. This can be done in a single query, with the disadvantage of bringing more data from the DB.
When you delay the load until the actual collection is accessed, it is called lazy loading, because you are only getting the childs when they are strictly required. This has the benefit of getting only the data when its needed, at the cost of extra queries (for mor on this topic you can query google for "N+1 select hibernate" for example).
If you want to trigger the query for retrieving the childs when the collection is being accessed, you need some sort of callback/interception on the childs collection. This is done through a proxy on the collection, so you can intercept every access to the collection to get data from the db. That's why you need a proxy/interception library such as Castle.
Lazy loading = waiting until code explicitly accesses a property/collection before loading it from the database.
Eager loading = proactively loading that data ahead of time, regardless of whether the code ever uses it or not.
Proxies are used to intercept access to said properties/collections in order to instigate the load.