Using cascade in NHibernate
I have two classes, call them Monkey and Banana, with a one-to-many bidirectional relationship.
Monkey monkey = new Monkey();
Banana banana = new Banana();
monkey.Bananas.Add(banana);
banana.Monkey = monkey;
hibernateService.Save(banana);
When I run that chunk of code, I want both monkey and banana to be persisted. However, it's only persisting both when I explicitly save the monkey and not vice versa. Initially, this made sense since only my Monkey.hbm.xml had a mapping with cascade="all"
.
<set name="Bananas" inverse="true" cascade="all">
<key column="Id"/>
<one-to-many class="Banana"/>
</set>
I figured I just needed to add the following to my Banana.hbm.xml file:
<many-to-one name="Monkey" column="Id" cascade="all" />
Unfortunately, this resulted in a Parameter index is out of range
error when I tried to run the snippet of code. I investigated this error and found this post, but I still don't see what I'm doing wrong. I have the relationship mapped once on each side as far as I can tell. For full disclosure, here are the two mapping files:
Monkey.hbm.xml
<class name="Monkey" table="monkies" lazy="true">
<id name="Id">
<generator class="increment" />
</id>
<property name="Name" />
<set name="Bananas" inverse="true" cascade="all">
<key column="Id"/>
<one-to-man开发者_StackOverflow中文版y class="Banana"/>
</set>
</class>
Banana.hbm.xml
<class name="Banana" table="bananas" lazy="true">
<id name="Id">
<generator class="increment" />
</id>
<property name="Name" />
<many-to-one name="Monkey" column="Id" cascade="all" />
</class>
The Parameter index is out of range error is due to your mappings. You have Id mapped as both the primary and foreign keys in the relationships.
The child mapping (Banana) need not have the cascade attribute. If one Banana is deleted, the Monkey might still have other Bananas, but when a Monkey gets changed, all its Bananas should be changed accordingly, so only the Monkey needs to have the cascade attribute
For future reference, you should also include your database schema for questions like this, as it can be hard to validate the mapping file without knowing the schema.
My guess is that you've screwed up your foreign keys. You say that the relation is a one-to-many, so that means Banana has a foreign key to the monkey table, correct? The standard naming for this foreign key column would be MonkeyID, and that is what appears to be missing in your mappings - all your column names seem to be ID. James Ide answered on similar lines and then you said "Id is the name of the primary key column in both tables. What should my relationship mappings look like?" - indeed, its quite fine for the name of the primary key column to be Id on both tables, but that still doesn't describe the relationship. As I mentioned above, you need a foreign key for the relationship.
You should find that the cascade problem sorts itself out once you fix your relationship. The behavior that people usually want from a cascade is to cascade deletes from the parent to the child, but not vice versa, in which case, you probably want cascade="save-update" on the many-to-one element instead of cascade="all".
Finally, as a shameless plug, have you considered trying Fluent NHibernate? You will probably find it easier to learn than hbm xml syntax.
精彩评论