2011-01-21 8 views
5

Attualmente sto lavorando su un piccolo progetto ASP.NET MVC.
Sto cercando di implementare NHibernate a persistere su un database MS SQL Server. Dopo aver passato lunghe ore a studiare DDD e altri progetti trovati su Internet, ho deciso di scegliere il modello di repository. Ora sto affrontando un dilemma.
Ho davvero bisogno di un repository quando uso Nhinbernate?
Non sarebbe meglio avere un livello di servizio (non ho un livello di servizio al momento) che interagisce con Nhinbernate evitando di scrivere quante volte qualcosa di simile:ASP.NET MVC, Nhibernate e repository per piccoli/medi progetti

public Domain.Reminder GetById(Guid Code) 
{ 
    return (_session.Get<Domain.Reminder>(Code)); 
} 

public Domain.Reminder LoadById(Guid Code) 
{ 
    return (_session.Load<Domain.Reminder>(Code)); 
} 

public bool Save(Domain.Reminder Reminder) 
{ 
    _session.SaveOrUpdate(Reminder); 
    return (true); 
} 

public bool Delete(Domain.Reminder Reminder) 
{ 
    _session.Delete(Reminder); 
    return (true); 
} 

ho trovato un vecchio Il POST di Ayende che è contro i repository.
So che c'è un grande dibattito intorno a questi temi e la risposta è sempre ... dipende, ma mi sembra che con troppi strati di astrazioni le cose si fanno più complicate e difficile da seguire.
Mi sbaglio?

+0

Solo una piccola nota. Non esiste un progetto medio-piccolo, per ora può essere piccolo, ma domani il tuo manager ti chiederà un'altra funzionalità, e poi un'altra e un'altra, e alla fine avremo un progetto enorme con un'architettura medio-piccola . Non mi piace molto il Big Design Up Front, ma a volte devi pensare un po 'più avanti. – goenning

+0

Sono d'accordo con te completamente ma, davvero, non riesco a vedere il vantaggio nell'utilizzo del repository se non per il fatto che non potrei usare nihbernate in futuro. Sta generando molto lavoro extra che non posso giustificare al momento. – LeftyX

risposta

7

Ayende era contro la scrittura di un repository nel modo in cui l'hai fatto per i motivi per cui hai fatto questa domanda, è un codice ripetitivo e NH può gestirlo comunque. Egli sostiene semplicemente chiamando l'NH direttamente come se fosse un deposito, e smettila di preoccupartene.

Ho praticamente d'accordo con lui. Non c'è davvero molto da guadagnare se non per più lavoro.

+0

Devo confessare che questa è la risposta che volevo sentire :-) – LeftyX

0

ho trovato alcuni motivi per cui si dovrebbe usare Repository/DAO/qualunque cosa.

  1. Test unità. Non ho mai provato a simulare/stub un ISession, ma direi che dovrebbe essere molto più complesso di una copiatura o di un'ostruzione di un repository/interfaccia DAO.
  2. Riutilizzo del codice. Se scrivi la tua query direttamente nei tuoi Servizi/Controller, finirai per duplicarla quando dovrai riutilizzare una query specifica. Se lo hai wrapper in un repository, basta chiamare il suo metodo.
  3. Single Responsibility Principle. Diffondere le tue domande attorno ai tuoi Controller ti fa infrangere questo principio.
  4. Dipendenza di NHibernate. Ok, questo è difficile, ma se hai bisogno di cambiare il tuo ORM, i repository lo rendono più facile (guarda, è più facile, non facile :)). O anche quando è necessario modificare l'origine dati utente da un database a Microsoft Active Directory, sarebbe più semplice.

Questo è tutto per sapere, non ricordo altro.

+0

Grazie Oenning. Non voglio scrivere query nei miei controller ma in un livello di servizio. Penso che sia un buon posto per mettere anche una logica di business. Non sarebbe nell'interfaccia utente e sarebbe riutilizzabile se voglio collegare il mio livello di servizio da qualche altra parte. Dipendenza da inibitore. Beh, sì, posso essere d'accordo ma non penso che succederà presto e non penso sia così diverso dal cambiare un repository. Grazie comunque. – LeftyX

+0

1. Se si simulano i repository, si sta utilizzando il pattern anti del "fixture noto". 2. Nulla dice che non è possibile creare astrazioni nel proprio livello di servizio. Questo è completamente falso. 3. Niente affatto. Stai andando a chiamare il db da qualche parte. Non importa se in un servizio o in una chiamata al metodo repo o in una parte del controller. Ancora lo stesso codice. Il controller è ancora responsabile dell'interrogazione del db. – jfar

+0

@jfar 1. Qual è l'anti modello di prova noto? Non ne ho mai sentito parlare. Sobro sempre i miei repository. 2. Se ho ottenuto ciò che hai detto giusto, finirai con lo stesso design di un repository ma lo chiamerai qualcos'altro. Hai qualche esempio di questo? Mi piacerebbe vedere un po 'di codice su questo. 3. Il controller non è responsabile per l'interrogazione del db, ha bisogno di chiedere a qualcun altro di farlo. Riceve la richiesta e in base a essa delega compiti ad altre classi e sceglie la vista successiva. – goenning

4

Utilizzare un repository generica, invece. Un repository per classe può facilmente essere eccessivo.

Io uso un repository con i metodi Get, Load, Save e vari metodi Matching (uno per Linq e uno per le mie query di dominio).

L'ultimo metodo accetta un'implementazione ICreateCritiera. Di seguito l'interfaccia e una sua implementazione.

public interface ICreateCriteria<T> : ICreateCriteria 
{ 
    DetachedCriteria GetCriteria(); 
} 

public class ChallengesAvailableToRound : ICreateCriteria<Challenge> 
{ 
    private readonly Guid _roundId; 

    public ChallengesAvailableToRound(Round round) 
    { 
     _roundId = round.Id; 
    } 

    public DetachedCriteria GetCriteria() 
    { 
     var criteria = DetachedCriteria.For<Challenge>(). 
      CreateAlias("Event", "e"). 
      CreateAlias("e.Rounds", "rounds"). 
      Add(Restrictions.Eq("rounds.Id", _roundId)); 

     return criteria; 
    } 
} 

Questo mi consente di suddividere le query nelle proprie classi e riutilizzarle facilmente in tutto il mio progetto.

+0

Mi piace la tua idea, Kenny. Proverò a lavorarci sopra. Grazie – LeftyX

+0

Kenny, penso che la tua soluzione sia abbastanza buona per me. Grazie. – LeftyX

Problemi correlati