NHibernate e modello di dominio complesso su un database legacy

3

Sto cercando di refactoring (in realtà, riscrivere) un'applicazione che attualmente utilizza solo stored procedure per accedere al database (centinaia di SP). Il mio obiettivo è usare Nhibernate e seguire il miglior design il più possibile. Ma dal momento che il database (e gli SP) sono usati da dozzine di altre app, non posso davvero cambiare il design del db. E, naturalmente, è terribile.

Sto affrontando un problema di progettazione e non riesco davvero a trovare una buona soluzione. Ho un tavolo chiamato film che contiene film, ma questi film possono essere "cose" differenti. Ad esempio, questa tabella contiene film e episodi di programmi televisivi e l'unico modo per conoscere la differenza è un campo chiamato "episodio" che è impostato su 0 per i film e 1 per gli episodi.

Il mio obiettivo è di esporre la seguente gerarchia di classi:

public abstract class Program {}
public class Episode : Program {}
public class Movie : Program {}

Attualmente ho mappato l'intera tabella di filmati a una classe di modello MoviesModel e poi ho creato la mia classe Episode / Movie tramite AutoMapper e un metodo factory nella classe Program:

public static Program Load(MoviesModel movieModel)
    {
        if (movieModel.Episode > 0)
            return Mapper.Map<Episode>(movieModel);
        return Mapper.Map<Movie>(movieModel);
    }

Questo sembra davvero sbagliato a molti livelli: ho un modello anemico di dati dal momento che il mio FilmModel è totalmente privo di qualsiasi logica di business, la roba dell'autoappaltatore diventa davvero difficile da mantenere quando aggiungo molte altre entità con relazioni a Movies, e mi interrompo il pigro caricamento con AutoMapper.

Ho sentito parlare della mappatura di Nhibernate, ma in realtà non risolve il mio problema, ma crea solo componenti secondari di una classe.

Quindi le mie domande sono:

  • Idealmente, dove dovrebbe essere la mia logica aziendale? Immagino nella classe MoviesModel ma non mi piace l'idea di esporre i miei campi di database.
  • C'è un modo con Nhibernate per mappare la stessa tabella in classi diverse in base al valore di un campo?
  • C'è un punto in cui racchiudere gli oggetti Nhibernate se voglio fornire un'API pubblica "pulita"?

Il mio obiettivo è creare una libreria di base che verrà utilizzata (si spera) su altre app legacy, quindi voglio fornire un'API pulita con metodi logici e senza esporre il pasticcio del database anche se devo ancora occuparmene.

Grazie per l'aiuto che mi ha dato nella giusta direzione.

    
posta Dawmz 18.07.2013 - 01:10
fonte

2 risposte

1

Purtroppo non conosco molto di AutoMapper, ma posso offrire una soluzione alla tua seconda domanda. Fluent NHibernate è uno strumento per aiutare i tuoi mapping di NHibernate, permettendoti di configurarli in modo programmatico piuttosto che usare XML. Uno dei metodi che puoi chiamare quando imposti i tuoi mapping è DiscriminateSubClassesOnColumn() che ti consente di specificare la colonna del database che verrà utilizzata per creare le sottoclassi. Quindi nelle sottoclassi si specifica il DiscriminatorValue che può essere un enum.

Ecco come immagino siano le tue mappature (codice non testato):

public class ProgramMap : ClassMap<Program>
{
    public ProgramMap()
    {
        //map your fields as normal, eg: Map(p => p.Id), Map(p => p.Name)
        DiscriminateSubClassesOnColumn<int>("Episode");
    }
}

public class MovieeMap : SubclassMap<Movie>
{
    public MovieMap()
    {
        DiscriminatorValue(0);
    }
}

Il problema potrebbe in realtà specificare il DiscriminatorValue per i tuoi film, ma spero che questo ti dia qualcosa da fare. Per riferimento ho utilizzato i seguenti link per mettere insieme questa risposta in modo che possano valere la pena dare un'occhiata nel caso in cui mi sia sfuggito qualcosa.

Si noti che se non si specifica DiscriminatorValue, Fluent NHibernate presuppone che la colonna discriminator contenga il nome della propria classe (che sarebbe un design terribile del database!).

    
risposta data 19.07.2013 - 20:42
fonte
-1

@Dawmz, non sono un grande fan dei framework ORM. Nota che sono uno sviluppatore del Database Valentina, quindi sappi come funzionano le cose internamente in dbs.

Nel tuo caso hai già centinaia di SP usati da dozzine (!) di altre app.

Questo è lo scenario migliore per gli SP, perché hai un posto centrale dove una volta presente la logica. Se rimuovi qualche SP, allora dove andrà la logica di quel SP? In dozzine di posti? Probabilmente su lingue diverse? Strada per l'inferno.

Come ho capito che questi SP sono stati sviluppati da qualcuno prima che tu venga? Lui / loro hanno fatto un ottimo lavoro. Non spezzare le cose.

    
risposta data 24.08.2013 - 09:02
fonte