Affichage des articles dont le libellé est nhibernate. Afficher tous les articles
Affichage des articles dont le libellé est nhibernate. Afficher tous les articles

lundi 7 octobre 2013

Injection de dépendance sur les controllers WebApi MVC (ApiController)

Bonjour à tous,
Dans un précédent article, je vous parlais de la mise en place de WEB Api avec les instructions MVC 4. Dans l’article, je ne parlais pas d’injection de dépendance, très souvent utilisée avec NHibernate par exemple (ce qui est mon cas).
Pour cela quelques étapes sont nécessaire pour faire le paramétrage de cette injection. MVC a déjà tout prévu pour nous :)
  • Modification du Global.asax
  • Utilisation de IHttpControllerActivator
  • Utilisation de Windsor Castle
Avant de rentrer dans le vif du sujet, attardons nous un petit moment sur l’injection de dépendance. Comment résumer cette notion sur un blog ? Hum pas évident. pour ma part je l’expliquerai avec une boite (container – conteneur en français ^^) qui connait les définitions des (de nos) objets.
De ce faite, c’est ce container qui construira/fabriquera/instanciera a la demande les objets nécessaire a l’exécution du code. L’intérêt de cette méthode est de rendre autonome au maximum nos classes (dépendance). Généralement cette dépendance, se voit au constructeur; ce dernier disposera alors comme paramètre l’ensemble des dépendances a résoudre lors de l’instanciation.
Ce n’est pas une notion facile a appréhender / comprendre. Moi même j’ai eu beaucoup de mal au début. Cependant, l’intérêt est tout de suite parlant dès lors ou vous avez a faire a des projet utilisant, ou nécessitant l’utilisation de ce mécanisme.

Global.asax

Le point d’entré de l’application permet d’exécuter le paramétrage de notre/nos injection(s). Dans notre cas, nous alors donc remplacer la “routine” du Controller sur nos  Web API, par notre propre “Activator” qui se positionnera donc entre la demande de la requête et son traitement. Permettant ainsi de résoudre, et de fournir le contrôleur adéquate (comprendre: Castle.Windors instanciera alors notre Controller avec les dépendances et le retournera a MVC).
Il est important de noter qu’il faut distinguer les routes de type WebAPI et les autres (mvc classique). L’injection ne sera pas la même, on passera alors par la fabrique de controller (ControllerBuilder.Current.SetControllerFactory(controllerFactory) )

protected void Application_Start()   
{

[…]

GlobalConfiguration.Configuration.Services.Replace(typeof(System.Web.Http.Dispatcher.IHttpControllerActivator), new WindsorCompositionRoot(container.Kernel));

}

IHttpControllerActivator

Une fois l’appel fait dans notre Application_Start, nous fournissons alors a notre Activator le Kernel (notre container de référence), pour que ce dernier puisse piocher dedans afin de faire l’instanciation.
L’interface est assez simple; 2 méthodes
- Create : création du controller en question, on va résoude (resolve) dans notre container la référence, et retourner ce dernier.
- Le Dispose, il faut lors de la fin d’execution de la requete HTTP (webapi) que les ressources acquises soient libérées. On implemente alors un classe Disposable, utilisable a l’aide de RegisterForDispose.
public class WindsorCompositionRoot : IHttpControllerActivator   
{    
    private readonly IKernel kernel;

    public WindsorCompositionRoot(IKernel kernel)   
    {    
        this.kernel = kernel;    
    }

    public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)   
    {    
        var controller = (IHttpController)this.kernel.Resolve(controllerType);

        request.RegisterForDispose(new RessCtrlRelease(this.kernel, controller));

        return controller;   
    }

    private class RessCtrlRelease : IDisposable   
    {    
        private readonly IKernel kernel;    
        private IHttpController httpController;

        public RessCtrlRelease(IKernel kernel, IHttpController httpController)   
        {    
            this.kernel = kernel;    
            this.httpController = httpController;    
        }    
        public void Dispose()    
        {    
            this.kernel.ReleaseComponent(this.httpController);    
        }    
    }

}

Je ne sais pas si j’ai été suffisamment clair, c’est un sujet assez vague et complexe, mais j’espère que les bouts d’informations que j’ai mise en place permettront d’éclaircir et d’aider les développeurs que nous sommes.
Parce que beaucoup d’information existe sur la toile, un article m’a beaucoup aider : http://blog.ploeh.dk/2012/04/17/InjectingHttpControllerContextWiththeASP.NETWebAPI/
Articles en relation :

mardi 28 décembre 2010

IndexOutOfRangeException: Index xx non valide - Nhibernate

Bonjour,

La gestion de Nhibernate est très complexe ... et je me permet de noter l'erreur suivante qui intervient lors d'un Update :

System.IndexOutOfRangeException: Index 29 non valide pour ce OracleParameterCollection avec Count=29

C'est erreur est lié a la mise a jour de trop de champs (champs en doublons dans le fichier hbm.xml : mapping de Nhibernate). C'est souvent le cas lorsque vous avez un many-to-one pour une assoc et qu'il existe également une property sur le même champs.

A ce niveau la, Nhibernate ne sait pas quel champs prendre, il utilise donc les deux ... et plante joyeusement ^^.


[...]


Dans mon cas, 29 correspond au nombre de champs (property) mappées dans mon fichier xml.

Pour résoudre le problème, deux solutions sont disponibles :
1- Rajouter les attributs update="false" insert="false" sur la/les property

2- Supprimer soit le/les many-to-one soit la/les property


Bonne journée

mercredi 9 juin 2010

Ne pas mettre a jour une table/entité avec Nhibernate

Bonjour a tous,

Aujourd'hui je me suis confronté a un problème de mise a jour par Nhibernate. Je m'explique, j'ai un traitement qui récupère/parcours plusieurs objets/entités mappées depuis une vue (oracle) bien spécifique (jointures...).

Le souci c'est que je modifie les enregistrements de cette vue pour effectuer un certain nombre de contrôle. Suite a ces tests, j'ai une opération de suppression (delete) ou mise a jour (update). Pour ces deux commandes, je stipule deux choses sur la session :

this.Session.Update(entite);
this.Session.Flush();

Or dans mon cas j'obtiens une erreur sur un update non souhaité du type : 
NHibernate: UPDATE vue_qui_va_bien SET champ1 = :p0 WHERE id= :p1;:p0 = '00000', :p1 = 123
Deux solutions se présente alors pour la gestion des mise a jour des tables et objets.

1° Lecture seule - Readonly sur tout la table


En précisant le terme mutable="false", cela précise à Nhibernate de ne pas mettre a jour cette table (vue). Aucune commande Update ou Delete ne sera effectué ! Nickel c'est ce que je voulais.

http://www.dil.univ-mrs.fr/~massat/docs/hibernate-3.1/reference/fr/html/mapping.html#mapping-declaration-class
     mutable (optionnel, vaut true par défaut) : Spécifie que des instances de la classe sont (ou non) immuables.


2° Lecture seule - Readonly sur un ou plusieurs enregistrements

En précisant le terme update="false" sur le ou les champs en question. Nhibernate ne fera pas de mise a jour si celui ci est modifié.

En esperant que cela vous aide dans vos développements avec Nhiberate !

mardi 20 avril 2010

Clé composite, mapping et class avec Nhibernate

Il vous est peut etre déja arrivé d'essayer de mapper une table qui ne contient aucune clé primaire (ou alors qui est composé). Pour ma part, hier cela m'est arrivé !
C'est ce que je vais essayer de décrire dans les étapes suivantes.

Lors de l'execution et du mapping de NHibernate, logiquement (sans mettre de clé primaire dans votre fichier xml), vous devriez tomber sur ce message :
- “composite-id class must override Equals()”
- “composite-id class must override GetHashCode()”

Pour corriger cette erreur, il faut absoluement avoir une clé primaire. Dans notre cas, elle sera composée (de Contrat_ID et Code_Agn).

Voici notre mapping:

















Notre classe :
public class Allegement
{
    public virtual string Contrat_ID { get; set;}
    public virtual string Lot_Paie { get; set;}
    public virtual string Montant_ALLGT_1 { get; set;}
    public virtual string Code_Agn { get; set; }

    // nécessaire lors des clés composites
    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        Allegement a = obj as Allegement;
        if (a == null)
            return false;

        if (this.Contrat_ID == a.Contrat_ID && this.Code_Agn == a.Code_Agn)
            return true;
        else
            return false;
    }

    // necessaire lors des clés composites
    public override int GetHashCode()
    {
        int hash = 666; // ce que l'on veux 
        hash += (null == this.Contrat_ID ? 0 : this.Contrat_ID.GetHashCode());
        hash += (null == this.Code_Agn ? 0 : this.Code_Agn.GetHashCode());

        return hash;
    }
}}

Les élements a retenir de cet exemple sont :
- pas de mapping sans clé primaire
- la redefinition des méthodes "Equals" et "GetHashCode", des classes de bases

Pour plus d'information sur le mapping : http://nhforge.org/doc/nh/en/index.html dans la partie "5. Basic O/R Mapping"

mardi 13 avril 2010

Récupération valeur d'une séquence Oracle avec NHibernate

Bonjour à tous,

Aujourd'hui je vais vous présentez comment récupérer une valeur d'une séquence oracle (SEQ_NAME.NEXTVAL) à l'aide de NHibernate sans écrire la requête SQL. A vrai dire l'information n'est pas facile a dénicher sur le net.

Donc voici les quelques lignes de code qui permettent de récupérer la nouvelle valeur :

NHibernate.Dialect.Oracle10gDialect dial = new NHibernate.Dialect.Oracle10gDialect();
string sqlString = dial.GetSequenceNextValString("SEQ_NAME"); // génère Select SEQ_NAME.NEXVAL FROM DUAL

ISQLQuery sqlQuery = _session.CreateSQLQuery(sqlString);
return sqlQuery.UniqueResult().ToString();

C'est plutôt simple, et donc il est facile d'étendre vos objets pour rendre cette partie un peu plus générique ;)

Bonne journée à tous

mercredi 17 février 2010

Mise à jour partielle d'entités NHibernate et MVC

Bonjour,

Suite a des petits problèmes de compréhension de NHibernate et MVC sur la modification des objets, je me permet de mettre un petit billet pour expliquer mes problèmes et pour montrer comment je les aient résolus.

Initialement dans mon controller, j'ai une méthode en POST qui souhaite mettre a jour un article :

// fonctionne si tous les champs du formulaire doivent etre mise a jour or dans mon cas, la date de création/modif
// ne doivent pas etre mis a jour !
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Article articleToEdit) 
{
    if (this._service.EditArticle(articleToEdit))
        return RedirectToAction("Index");
    return View();
}

Cela fonctionne bien, sauf que pour mon article en édition, je n'ai pas rempli de date de création, de ce fait, l'objet "articleToEdit" a comme "01/01/0001" en valeur d'attribut datecreation.

Pour mettre a jour un article, il faut récupéré l'identifiant de l'article et travailler avec ce dernier pour le mettre a jour.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection collection)
{
    Article articleToEdit = this._service.GetArticle(id);
    UpdateModel(articleToEdit);

    if (this._service.EditArticle(articleToEdit))
        return RedirectToAction("Index");
    return View();     
}

En fait, on va tout d'abord récuperer l'article a éditer, et à l'aide de la méthode "UpdateModel" (implémentée par le controller), cela nous permet de mettre a jour notre articleToEdit avec les informations de notre formulaire.
En débuggage on le voit tres bien :

Avant :
Apres :

mercredi 3 février 2010

TP Active Record - Articles/Catégorie [Compil] (Partie 4)

Nous voici dans la 4nd section TP Active Record, ceci est l'explication pas à pas d'un TP de création de site Web permettant de créer des articles et d'en associer des catégories.
Voici la liste des articles disponibles :
Dans cette partie nous allons verifier le fonctionnement du code que vous avons produit dans les parties précédentes.

TP Active Record - Articles/Catégorie [NHibernate] (Partie 3)

Nous voici dans la 3nd section TP Active Record, ceci est l'explication pas à pas d'un TP de création de site Web permettant de créer des articles et d'en associer des catégories.
A ce niveau la nous utiliserons le pattern  " ActiveRecord " de l'API Castle Project utilisant NHibernate. ActiveRecord est un design pattern qui permet de masquer la complexité des interactions avec la base de données en évitant d'écrire du code SQL
Le gros avantage avec ce pattern c'est qu'il permet d'écrire aussi dans une seule et même classe le mapping base de données et la classe/l'objet métier. Je vous invite à lire l'article montrant les différences de fonctionnement entre " ActiveRecord " et un accès classique NHibernate (Mapping_NHibernate_2010-01 ...).

TP Active Record - Articles/Catégorie [Archi] (Partie 2)

Nous voici dans la 2nd section TP Active Record, ceci est l'explication pas à pas d'un TP de création de site Web permettant de créer des articles et d'en associer des catégories.
Nous allons décrire les étapes pour créer une solution depuis Visual Studio 2008 simple et pratique pour la réalisation de notre TP. Je rappel que cette solution n'est pas l'unique solution, mais me convient pour l'instant.

TP Active Record - Articles/Catégorie [Intro] (Partie 1)

Bonjour a tous,

Dans ce 1er TP, nous allons créer un site permettant de gerer des articles associés a des catégories. Un sujet classique, cas d'école, qui nous permettra de voir les différents concepts : NHibernate, MVC 3.5, Castle Active Record, Linq et bien d'autres.
Voici le sommaire que je vous propose :

lundi 1 février 2010

Portage du tutoriel Contact Manager de Entity Framework à NHibernate (et Oracle)

De la même maniere que mon cher collègue Michel, sur son blog (Linq To SQL). Je vais vous présentez comment migrer de Entity Framework à NHibernate + Oracle.

Tout d'abord les informations nécessaires

Création du modèle
Tout de suite, ici il ne s'agit pas de faire du drag'n drop de vos tables avec de beaux object Visual Studio ! Il faut coder lignes par lignes notre modele de persistance.
Tout d'abord supprimez :
  • le fichier "modele" .edmx
  • les références inutiles (System.Data.Entity)
  • le repository : EntityContactManagerRepository.cs

vendredi 8 janvier 2010

NHibernate et les Séquences Oracle

Bonjour, voici un nouveau billet concernant l'utilisation de NHibernate avec Oracle et .Net.

Le problème rencontré était l'utilisation d'un identifiant unique pour la création de données dans une table. Comme vous le savez peut etre déja, Oracle n'a pas de type "AUTO-INCREMENT"/"IDENTITE" comme Mysql ou SqlServeur. Pour pallier a cette contrainte il "suffit" de créer une SEQUENCE et d'utiliser cette derniere pour prendre de maniere unique l'identifiant de notre table.

Le but de ce billet n'etant pas d'expliquer les Sequence, je vous laisse la lecture de ce site pour la compréhension : http://www.commentcamarche.net/contents/oracle/oracseq.php3

Revenons a nos mouton : NHibernate est-il capable de gérer nativement les identifiants uniques ? C'est effectivement le cas ! Chouette ! Comment vous allez me dire ? C'est pas très compliqué, il suffit de modifier votre fichier de mapping comme ceci :

jeudi 17 décembre 2009

Intellisense Visual Studio 2008 et NHibernate

Bonjour,

Pour les utilisateurs de NHibernate (mapping Objet <-> Base de donnée), la création de fichier de configuration de "mapping" est obligatoire. Pour que cela soit beaucoup plus pratique et rapide voici comment rajouter l'intellisense de VS 2008 (et 2005 fonctionne aussi)

1° Ajouter un fichier XML vide à votre solution

2° Un nouveau menu apparait dans l'éditeur >> XML << Cliquer sur Schémas...