Support of Many-to-Many 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 many-to-many mapping of сomponent navigation properties.
To find out more about the rest of the types of сomponent navigation properties mapping, see the article devoted to them here.

Many-to-many mapping of component navigation properties:

This type of mapping can be efficient in case there are several entities in the model connected with many-to-many associations with the same entity, and also possibly (but not obligatorily) having some set of properties similar in meaning and structure.

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

Example:

The database contains the Companies, Factories and CompanyFactories tables, the last one provides references for a many-to-many relation between the Companies and Factories tables.
The database also contains the Shops and CompanyShops tables, the latter also provides references for a many-to-many relation between the Companies and Shops tables.

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

The tables diagram is as follows:

Diagram

We perform the following sequence of operations:

  • create a NHibernate model;
  • add the Companies, Factories, Shops, CompanyFactories and CompanyShops tables to the model.

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

Initial Model

We select the ShopAddress, ShopCity, ShopRegion, ShopPostalCode, ShopCountry properties and the Companies navigation property of the Shop entity, drag and drop them into a separate complex type and call it ‘ContractorType’; an association appears between this complex type and the Company class and from now on it is the СontractorType complex type that contains the Companies navigation property, and instead of the set of the moved properties the Shop entity contains a property with the type equal to ContractorType, let’s call it Contractor. This is not mandatory, but for the sake of convenience we remove the Shop prefix from the names of the properties and columns of the ContractorType complex type in the default mapping.

The association between ContractorType and the Shop entity looks as follows:

Association Editor window for a many-to-many association

As can be seen from the Association editor dialog box, part of relation settings is in the association itself, for the many-to-many case there is also a default mapping for the foreign key column of the join table for 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 Shop entity properties set, custom mapping of these properties was defined for this entity automatically during dragging and dropping and looks as follows:

Shop entity properties mapping

Now it is necessary to delete the association between the Company and Factory entities, and also delete the FactoryAddress, FactoryCity, FactoryRegion, FactoryPostalCode, FactoryCountry properties of the Factory entity. Instead of these properties set, describing the address and the list of counterpart’s products, it is necessary to add one property with the name ‘Contractor’ and the type equal to ContractorType. Then it is necessary to set custom mapping for the Factory entity’s Contractor property to the Factories table columns as displayed below:

Contractor property custom mapping

As a result we have the following model:

Resulting Model

The code generated for the model is as follows:

As can be seen from the generated code, a property is generated in the ContractorType class, containing a reference to the Company class, and the classes Shop and Factory in their turn both contain a Contractor property with type equal to ContractorType, and these properties describe addresses and the list of products of the manufacturer and distributor 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.