Chapter 1 examples of nhib.pdf documentation Translation: Parent/Child

Source: Internet
Author: User
Chapter 1 Example: Parent/Child

Directory

About collections

Bidirectional one-to-many)

Cascading lifecycle)

Cascading Update (Using cascading) update())

Conclusion

Most of the people who just came into contact with NHibernate started with modeling the parent-child relationship (parent/child type relationship. There are two methods to create a parent-child relationship. The simple and intuitive method is to establish<one-to-many>FromParentPointChildThis is especially true for new users. But there is another way to declare Child as<composite-element>(Combination element ). We can see that the use of one-to-multiple associations in NHibernate is closer to the semantics of the common parent/child relationship than the composite element. Next we will explain how to use bidirectional one to mutual association with cascades to establish an effective and beautiful parent/child relationship. This is not difficult!

About collections

In NHibernate, the object class uses collection as a logical unit of its own, rather than multiple entities. This is very important! It mainly includes the following:

  • When an object in the collection is deleted or added, the version value of the object that owns the collection increases progressively.

  • If an object removed from the collection is an instance of value type, such as composite element, the Persistence State of the object will be terminated, the corresponding records in the database will be deleted. Similarly, adding a value type instance to the collection will immediately make it persistent.

  • On the other hand, if an object (one-to-multiple or multiple-to-multiple) is removed from a one-to-multiple associated collection ), by default, this object will not be deleted. This behavior is completely logical-changing the internal state of an object should not cause the object associated with it to disappear! Similarly, adding an object to the collection object will not make it persistent.

In fact, the default action to add an object to the Collection object is to create a connection between the two objects, and delete the connection when removing the object. This kind of processing is suitable for all situations. The parent-child relationship itself is not suitable in all cases, because whether the Sub-object exists depends on the lifecycle of the parent object.

Bidirectional one-to-many)

Let's start with a simple example. Suppose we want to implementParentTo classChild.

<set name="Children"> <key column="parent_id" /> <one-to-many class="Child" /></set>

If we run the following code

Parent p = session.Load( typeof( Parent ), pid ) as Parent;Child c = new Child();p.Children.Add( c );session.Save( c );session.Flush();

Nhib.pdf generates the following two SQL statements:

  • OneINSERTStatement used to create an objectcCorresponding database records

  • OneUPDATEStatement used to create a slave objectpTo objectcConnection

This is not only inefficient, but also violates the columnparent_idNon-empty limit.

The underlying reason is that the objectpTo objectc(Foreign keyparent_id) Is not consideredChildPart of the object status is not inINSERTIs created. The solution isChildSet ing at one end.

<many-to-one name="Parent" column="parent_id" not-null="true"

(We also needChildAddParentAttribute)

Current entityChildIn the management connection status, we useinverseAttribute.

<set name="Children" inverse="true"> <key column="parent_id" /> <one-to-many class="Child" /></set>

The following code is used to add a newChild

Parent p = session.Load( typeof( Parent ), pid ) as Parent;Child c = new Child();c.Parent = p;p.Children.Add( c );session.Save( c );session.Flush();

Now, there will be only oneINSERTThe statement is executed!

To make things well organized, you canParentAdd oneAddChild()Method

public void AddChild( Child c ) { this.Children.Add( c ); c.Parent = this;}

AddChildSimplified the code

Parent p = session.Load( typeof( Parent ), pid ) as Parent;Child c = new Child();p.AddChild( c );  //  session.Save( c );session.Flush();
Cascading lifecycle)

Call each objectSave()() The method is very troublesome. We can use cascade to solve this problem.

<set name="Children" inverse="true" cascade="all"> <key column="parent_id" /> <one-to-many class="Child" /></set>

After cascade configuration, the code is simplified:

Parent p = session.Load( typeof( Parent ), pid ) as Parent;Child c = new Child();p.AddChild( c );session.Flush();
Note:

Cascade dependencyunsaved-valueAttribute ). Make sure that<id>Default Value andunsaved-valueSame.

Similarly, when you save or deleteParentWe do not need to traverse children. The following code is deleted from the database.pAnd all its children.

Parent p = session.Load( typeof( Parent ), pid ) as Parent;session.Delete( p );session.Flush();

However, this code

Parent p = session.Load( typeof( Parent ), pid ) as Parent;Child c = null;foreach( Child child in p.Children ) { c = child; // only care about first Child break;}p.Children.Remove( c );c.Parent = null;session.Flush();

Will not be deleted from the databasec; It will only deletep(And may cause a violationNOT NULLConstraints, in this example ). You need to callChildOfDelete()Method.

Parent p = session.Load( typeof( Parent ), pid ) as Parent;Child c = null;foreach( Child child in p.Children ) { c = child; // only care about first Child break;}p.Children.Remove( c );c.Parent = null;session.Delete( c );session.Flush();

In our example, if we specify that there is no parent object, the sub-object should not exist. If we remove the sub-object from the collection, we actually want to delete it. To achieve this requirement, you must usecascade="all-delete-orphan".

<set name="Children" inverse="true" cascade="all-delete-orphan"> <key column="parent_id" /> <one-to-many class="Child" /></set>

Note: Even if you specifyinverse="true"The cascade operation is still executed when the collection is traversed. To insert, delete, and update sub-objects through cascading, you must add them to the collection and only callChild.ParentSetter is not enough.

Cascading Update (Using cascading) update())

Suppose we start fromISessionAnParentObject, the user interface has modified it, and we want to call it in a new ISessionUpdate()To update it. ObjectParentA set of sub-objects is included. Since cascade update is enabled, nhib.pdf needs to know which sub-objects are new and which are existing in the database. Let's assume thatParentAndChildThe object's identity property type isSystem.Int32. NHibernate uses the value of the identifier property to determine which sub-objects are new. (You can also use the version or timestamp attribute)

unsaved-valueAttribute is used to indicate the identity property value of the new instance. The default value is "null". For. net Value Type (ValueTypes), this is not a good default value, so you need to provideunsaved-value.

If we use the original type as the identification type, we must write the following When configuring the Child class ing:

<id name="Id" type="Int64" unsaved-value="0"> 

ForChildIng. (There are alsounsaved-valueAttribute is provided to the version and timestamp attributes (property ing)

The following code is updated:parentAndchildObject, and insertnewChildObject.

// Parent and child were both loaded in a previous page ious sessionparent. addChild (child); Child newChild = new Child (); parent. addChild (newChild); session. update (parent); session. flush ();

Okay. This is very convenient for Automatic Generation of identifiers. But what about self-assigned identifiers and composite identifiers? This is a little troublesome, becauseunsaved-valuesThe new object (ID specified by the user) and the previous object cannot be distinguished.ISessionThe object to load. In this case, you may need to give NHibernate some tips before calling update (parent:

  • In this class<version>Or<timestamp>Attribute ingunsaved-value="null"Orunsaved-value="negative".

  • ExecuteUpdate( parent )Previously, Setunsaved-value="none"And explicitly callSave()Create a new sub-object in the database

  • ExecuteUpdate( parent )Previously, Setunsaved-value="any"And explicitly callUpdate()Update mounted sub-objects

noneIt is a self-assigned ID and a composite IDunsaved-value.

Conclusion

This problem is often confusing for new users. It is indeed not easy to digest. However, after some practices, you will feel more and more comfortable. The parent-child object mode has been widely used in nhib.pdf applications.

In the first section, we mentioned another solution. The semantics of the composite element is equivalent to that of the parent-child relationship, but we have not discussed it in detail. Unfortunately, composite elements have two major limitations: composite elements cannot have collections, and they cannot be sub-objects of any other entity except for the unique parent object. (However, by using<idbag>Ing, which may have the proxy primary key .)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.