Support of Many-to-One Mapping for Component Navigation Properties in Entity Developer

This article explains and gives a practical example of how support of сomponent navigation properties is implemented in Entity Developer for NHibernate.
Support of this functionality includes the possibility of detaching to a complex type for further reusability not only scalar entity properties but also navigation properties with subsequent customization of complete mapping at the level of private mapping of a certain property with type equal to complex type of a certain entity.

There are several ways of component navigation properties mapping in NHibernate:

  • Many-to-one;
  • One-to-many;
  • One-to-one;
  • Many-to-many.

In this article we will consider the most popular of them, i.e. many-to-one mapping of сomponent navigation properties. We will not focus on one-to-many and one-to-one types of сomponent navigation properties mapping, as these types of mapping are not very common, besides, their usage and customization have little difference from the example under consideration and so are quite comprehensible. Many-to-many mapping is considered in details in the article Support of Many-to-Many Mapping for Component Navigation Properties in Entity Developer.

Many-to-one mapping of component navigation properties

This type of mapping can be efficient in case there are several tables in the database referring to the same details table using a foreign key constraint, and also, possibly (but this is not a must), having some set of fields matching in meaning and structure. Or the same table contains several sets of fields or foreign keys similar in structure, describing respectively several data objects similar in structure (e.g. when the same table containing descriptions of companies includes several matching sets of fields representing addresses of head and shipping offices).

Then, after creating a model, it makes sense to move the similar set of the corresponding scalar and navigation properties into a separate complex type, and replace every such set in entities with a property having type equal to complex type and an appropriate customization of private mapping for this property.

Example:

The database contains the Orders and Suppliers tables, which have a foreign key constraint with the Countries table. The Orders and Suppliers tables have the same fields containing address description, and also a foreign key column associated with the table containing country names with a foreign constraint.

The script for tables creation for SQL Server DBMS is as follows:

The tables diagram is as follows:

Database Diagram

We perform the following sequence of operations:

  • create a NHibernate model;
  • add the Orders, Suppliers and Countries tables to the model.

Before defining a complex type, the model looks as follows:

Initial Model

We select the Address, City, Region, PostalCode properties and the Country navigation property of the Supplier entity which are used to describe address, drag and drop them into a separate complex type and call it ‘AddressType’; an association appears between this complex type and the Country class and from now on it is the AddressType complex type that contains the Country navigation property, and instead of the set of the moved fields the Supplier entity contains a property with the type equal to AddressType, let’s call it Address.

The association between AddressType and the Country entity looks as follows:

Association Editor window for a many-to-one association

As can be seen from the Association editor dialog box, part of relation settings is in the association itself, for the many-to-one case there is also a default mapping for the foreign key column of an entity which will contain the property of the specified complex type, but if necessary, it can be changed to a custom one for a certain entity property. This will be shown in our example further in this article.

Since we created the complex type on the basis of the Supplier entity properties set, custom mapping of these properties was defined for this entity automatically and looks as follows:

Properties Custom Mapping

Now it is necessary to delete the association between the Order and Country entities, and also delete the ShipAddress, ShipCity, ShipRegion, ShipPostalCode properties of the Order entity. Instead of these properties set, describing the ship owner’s company address, it is necessary to add one property with the name ‘ShipAddress’ and the type equal to AddressType. As the column names of the address description and foreign columns in the Order entity do not match with the default mapping of the AddressType complex type properties and the default mapping of the association foreign column, it is necessary to set custom mapping for the Order entity’s ShipAddress property to these columns as displayed below:

ShipAddress property custom mapping

As a result we have the following model:

Resulting Model

The generated code for the model is as follows:

As can be seen from the generated code, a property is generated in the AddressType class, containing a reference to the Country class, and the classes Order and Supplier in their turn both contain a property with type equal to AddressType, and these properties describe addresses of the shipping company and vendor respectively.

The xml-mapping generated for the model looks as follows:

The NHibernate model for Entity Developer created in this example can be downloaded here

Comments are closed.