2010-12-01 12 views
1

Je suis en train de créer une application qui permet aux utilisateurs d'apporter des modifications aux objets, mais les modifications doivent être approuvées avant qu'elles ne soient rendues permanentes. J'utilise NHibernate.NHibernate persiste changement d'objet pour approbation

Comment géreriez-vous ce genre de scénario en utilisant? Existe-t-il des articles traitant de ce problème? Je pense à avoir deux tables pour chaque objet. Un pour l'état actuel et un pour l'état proposé. Ensuite, avoir un objet Generic ChangeRequest qui spécifie la suppression/insertion/mise à jour et le sujet qui veut être changé. Mais, je ne crois pas que NHibernate vous permettra d'avoir deux mappages différents pour le même objet.

Répondre

1

Les deux options du haut de ma tête ...

Chaque objet pourrait avoir un drapeau approuvé ou la date d'approbation. (Cela pourrait être encapsulé dans une classe de base commune.) Vous auriez besoin d'une clé composite incluant la colonne d'approbation (non recommandée - les touches composées sont une douleur) ou chaque objet pourrait avoir une clé métier en plus de la PK. Cela signifierait une table par entité avec des colonnes de métadonnées supplémentaires dans chaque table pour déterminer approuvé. (Vous pouvez décider de conserver ou non toutes les modifications.)

L'autre option serait deux tables distinctes pour chaque objet. Vous pouvez le faire en utilisant les noms d'entités, qui ont été introduites dans NH2.1. Plus facile de montrer un exemple. Nous avons seulement une définition de classe:

public class Foo { 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
} 

Nous avons deux fichiers hbm.xml. Notez l'attribut entity-name après la classe. Cela crée deux tables, Foo1 et Foo2. (Vous pouvez choisir vos propres noms via l'attribut table.)

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="NhHacking" assembly="NhHacking"> 
    <class name="Foo" entity-name="Foo1"> 
    <id name="Id"> 
     <generator class="native" /> 
    </id> 
    <property name="Name"/> 
    </class> 
</hibernate-mapping> 

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="NhHacking" assembly="NhHacking"> 
    <class name="Foo" entity-name="Foo2"> 
    <id name="Id"> 
     <generator class="native" /> 
    </id> 
    <property name="Name"/> 
    </class> 
</hibernate-mapping> 

Lorsque nous enregistrons les entités, nous fournissons le nom de l'entité avec l'opération:

var foo1 = new Foo {Name = "Foo1"}; 
var foo2 = new Foo {Name = "Foo2"}; 
session.Save("Foo1", foo1); 
session.Save("Foo2", foo2); 

Cela vous permet de sélectionner la table l'entité va à. Vous voudriez bien sûr encapsuler les noms d'entités dans une classe de constantes. Vous devez spécifier le nom de l'entité pour toutes les opérations (session.Get(), session.Save(), session.Update(), session.Delete(), etc.)

+0

Je ne savais pas que vous pouviez mapper le même classe à deux mappings. C'est probablement la façon dont je vais le gérer. Pourrais-je spécifier dans le fichier de mappage d'objet ChangeRequest le nom d'entité à utiliser pour ? De cette façon, je peux simplement appeler enregistrer sur ChangeRequest et il enregistrerait le à la table d'approbation en attente. – awilinsk

+0

Vous ne pouvez pas le faire out-of-the-box autant que je sache. Vous devez créer un fichier hbm.xml distinct pour chaque demande de changement . Ce ne serait pas un problème difficile à résoudre avec un peu de métaprogrammation sur l'objet Configuration. Après avoir lu dans votre configuration, vous pouvez modifier votre configuration.ClassMappings pour inclure le nom de l'entité, puis cloner chacun d'entre eux - en modifiant le nom de l'entité en ChangeRequest - et en l'ajoutant à la collection Configure.ClassMappings. Jamais fait exactement cela, mais cela devrait fonctionner ... –

0

Pour votre cas, je suggère que chaque objet aura la conception suivante: PropertyName, PropertyValue, PropertyStatus (propesed/approved). Par ce desing vous pouvez modifier vos objets d'une manière ou d'une autre tout en gardant un mapping pour le fichier. Par exemple, si une table personne doit avoir les colonnes ssn, nom, date de naissance .... Dans ce desing vous aurez 3 lignes:

 
In regular design 
----------------- 
ColumnName ColumnValue 
ID   1 
ssn   123 
name   xyz 
birthdate dd/mm/yyy 

This will be 
------------ 
PropertyName PropertyValue ObjectID PropertyStatus 
ssn   123    1   approved 
name   xyz    1   approved 
birthdate  dd/mm/yyyy  1   approved 

Pensez-y comme si elle est une table verticale où les lignes sont la colonne et vice versa.