Dans les articles précédents, nous avons vu comment sélectionner, insérer, mettre à jour des enregistrements avec NHibernate. Cependant, dans 99% des cas, une table n’est pas isolée dans une base de données, il y a la plupart du temps une (ou plusieurs) clé étrangère (Foreign key) donc un lien avec d’autres tables. C’est ce qui va nous occuper dans cet article.
Nous allons créer un objet (Table) “Produit” qui peut être attribué à plusieurs '”Catégorie”, nous allons donc créer deux objets “Product” et “Cateogry”, créer le relation au niveau des fichiers de mapping et ensuite créer une méthode de test qui va nous permettre de vérifier le bon fonctionnement. Pour être honnête étant un adepte du TDD (Test Driven Development), j’ai d’abord commencé par écrire la méthode de test, ensuite les classes et pour terminer les fichiers de mapping.
Voici la classe et le fichier de mapping de l’entité “Product”
public class Product
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual string Code { get; set; }
public virtual bool IsActive { get; set; }
public virtual float Price { get; set; }
public virtual IList<Category> Categories { get; set; }
public Product()
{
Categories = new List<Category>();
}
public virtual void AddCategory(Category category)
{
category.Product = this;
Categories.Add(category);
}
}
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Core.DomainModel" namespace="Core.DomainModel">
<class name="Product" table="Product">
<id name="Id" column="Id" type="Guid">
<generator class="guid.comb"/>
</id>
<property name="Name" length="50" not-null="true"/>
<property name="Code" length="50" />
<property name="IsActive" type="boolean"/>
<property name="Price" type="float"/>
<bag name="Categories" inverse="true" cascade="all" table="Category">
<key column="Product" foreign-key="FK_Product_Category"/>
<one-to-many class="Category"/>
</bag>
</class>
</hibernate-mapping>
On peut trouver quelques propriétés dont une est une liste de “Categgory” '(d’ou le nom “Categories”). Dans le constructeur, on initilise cette liste. La méthode “AddCategory” permet d’ajouter une catégorie à la list. Dans cette methode on constatera que la propriété “Product” de l’objet “Category” est assignée via le mot réservé “this”.
Voici la classe et le fichier de mapping de l’entité “Category”
public class Category
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual string Code { get; set; }
public virtual bool IsActive { get; set; }
public virtual Product Product { get; set; }
}
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MonApplication" namespace="MonApplication">
<class name="Category" table="Category">
<id name="Id" column="Id" type="Guid">
<generator class="guid.comb"/>
</id>
<property name="Name" length="50" not-null="true"/>
<property name="Code" length="50" />
<property name="IsActive" type="boolean"/>
<many-to-one name="Product" class="Product" />
</class>
</hibernate-mapping>
Pas la peine de s’étendre, il n’y a vraiment rien de spécial dans ce code que se soit au niveau du fichier de mapping que de la classe
Notre méthode de test :
[Test]
public void Test()
{
ISession session = GetSession();
using (ITransaction tx = session.BeginTransaction())
{
Product product = new Product() { Name = "Nouveau", Code = "XYZ" };
product.AddCategory(new Category() { Name = "NouvelleCategorie", Code = "NewCat" });
session.Save(product);
tx.Commit();
}
}
Nous allons dans cette methode, ouvrir une session (3), créer une transaction (9), ajouter une catégorie au produit (16) et sauvegarder le produit. La sauvegarde du produit va provoquer l’insertion au niveau de la base de données de la nouvelle catégorie et de l’assignation de celle-ci au produit.
Ci-dessous le code généré, on peut constater les deux INSERT un dans la table “Product” et l’autre dans la table “Category”. Les captures d’écran proviennent de NHProf qui est un debugger en temps réel que je ne peux que vous conseiller. Il a été conçu par Oren Eini plus connu sous le nom de “Ayende” et aussi un des développeurs de NHibernate.
Cliquer pour agrandir