ConfORM, NHibernate, Oracle e gli Integration Test

In questi giorni sto lavorando parecchio ad un’applicazione che usa Oracle come repository e NHibernate come framework di persistenza. Essendo questa un’applicazione “delicata” ho necessità di creare una serie di integration test che mi “garantiscano” il corretto funzionamento, in modo da non avere spiacevoli sorprese in fase post deploy.

Letta così la questione non presenta particolari criticità, ma ho dovuto affrontare un nuovo scenario riguardante Oracle e la sua gestione degli indici.

Prima di entrare nel dettaglio tecnico vorrei puntualizzare che la soluzione da me adottata è la conseguenza di una totale inesperienza relativamente al mondo Oracle, potrebbe quindi esistere una strada migliore e più corretta per arrivare alla soluzione (magari se la conoscete, datemi qualche consiglio Open-mouthed smile).

Fatta tale premessa provo a descrivere un po’ lo scenario. Nella mia installazione interna all’azienda ho un solo database engine di Oracle che contiene al suo interno l’applicazione di sviluppo, quella di test ed infine quella di quality assurance. Quindi, lato database, ho tre schema/utenti ben differenti denominati rispettivamente Dev, Test e QA, ed ognuno di questi ha le proprie tabelle con i propri dati, come mostrato dalla tabella seguente:

dev

test

QA

dev.users

test.users

qa.users

dev.roles

test.roles

qa.roles

dev.usersinroles

test.usersinroles

qa.usersinroles


Essendo l’applicazione in uno stato di sviluppo più o meno avanzato, il database delle linea dev non subisce molti “restyling”, al contrario del database dei test che viene cancellato e ricreato ad ogni test.

Il mio problema è nato proprio durante la fase di “drop & create” dello schema: questo viene creato correttamente, ma poi la procedura di NHibernate non completa correttamente il tutto perché, al contrario di quanto avviene per le tabelle, gli indici non sono legati ad uno specifico schema, sollevandomi una brutta eccezione del tipo “nome oggetto già utilizzato” (riferendosi all’indice che si stava cercando di creare).
Se si riosserva la tabella riportata in precedenza si può facilmente intuire che l’univocità del nome della tabella è data dalla combinazione dello schema con il nome della tabella stessa. Purtroppo o per fortuna (direi più per fortuna) questa “combo” non esiste per gli indici, il che si traduce nel dover creare indici con nomi differenti per ogni “environment” in quanto trasversali all’interno del database engine.

L’indice IX_ItemType non è dev.IX_ItemType!

La mia configurazione di NHibernate creava automaticamente degli indici per alcuni scenari (nello specifico per il “Table Per Class Hierarchy”) in modo da aiutare il database nell’eseguire le query. Con il supporto del buon Fabio ho creato un Applier per ConfORM (in realtà ho fatto copia ed incolla di quello esistente) che mi permette di stabilire un prefisso per tutti gli indici, in modo da avere un risultato tipo il seguente:

  • IX_MyIndex;
  • IX_Test_MyIndex;
  • IX_QA_MyIndex;

Una volta creato l’applier mi è bastato effettuare una merge dello stesso e, come per magia, tutti i test sono diventati verdi.
Per chi fosse interessato posto il codice dell’applier di ConfORM

public class DiscriminatorIndexNameApplier : IPatternApplier<Type, IClassAttributesMapper> {
    private readonly IDomainInspector domainInspector;
    readonly string indexPrefix;

    public DiscriminatorIndexNameApplier ( IDomainInspector domainInspector, string indexPrefix ) {
        this.domainInspector = domainInspector;
        this.indexPrefix = indexPrefix;
    }

    #region IPatternApplier<Type,IClassAttributesMapper> Members

    public bool Match ( Type subject ) {
        return domainInspector.IsTablePerClassHierarchy ( subject );
    }

    public void Apply ( Type subject, IClassAttributesMapper applyTo ) {
        applyTo.Discriminator ( dm => dm.Column ( cm => cm.Index ( indexPrefix + subject.Name + "EntityType" ) ) );
    }

    #endregion
}

 

e per il suo utilizzo:

IPatternsAppliersHolder patternsAppliers = ( new ImperugoPatternsAppliersHolder ( orm , NHConfiguration.Instance.IndexPrefix ) )
    .Merge ( new ConfORM.DiscriminatorValueAsEnumValuePack <Person, PersonDiscriminatorMap> ( orm ) )
    .Merge ( new ConfORM.DiscriminatorValueAsEnumValuePack <View , ViewDiscriminatorMap> ( orm ))
    .Merge ( new ConfORM.DiscriminatorIndexNameApplier ( orm, NHConfiguration.Instance.IndexPrefix ) );


dove l’ultima riga cambia la naming convention degli indici leggendo il prefisso dal file di configurazione. Enjoy!


Comments