Quando utilizzare il modello di repository

20

Recentemente ho letto che non è una buona pratica usare il pattern del repository in congiunzione con un ORM. Da quanto ho capito, questo è dovuto al fatto che l'astrazione che forniscono sul database SQL è troppo dispersiva per essere contenuta dal pattern.

Ho un paio di domande a riguardo:

  1. Che cosa fai se vuoi cambiare ORM? Avresti il codice ORM specifico nella tua applicazione se non lo conteni in un repository.

  2. Il modello di repository è ancora valido quando non si utilizza un ORM e si sta utilizzando ADO.NET per l'accesso ai dati e la compilazione automatica dei dati dell'oggetto?

  3. Se si utilizza un ORM ma non il modello di repository in cui vengono mantenute le query di uso comune? Sarebbe saggio rappresentare ogni query come una classe e avere una sorta di factory di query per creare istanze?

posta user1450877 10.10.2013 - 15:01
fonte

4 risposte

3

1) Vero, ma con quale frequenza si cambia ORM?
2) Direi di sì, perché un contesto ORM è una sorta di repository e nasconde un sacco di lavoro che comporta la creazione di query, il recupero di dati, la mappatura, ecc. Se non si utilizza un ORM, tale logica deve ancora risiedere da qualche parte. Non so se questo si qualificherebbe come il modello di deposito nel senso più stretto della parola anche se ...
3) Le query incapsulanti sono qualcosa che vedo spesso, ma di solito è più per scopi di test / stub. A parte questo, farei attenzione quando riusciamo una query tra diverse parti di un'applicazione, perché rischi di creare una dipendenza da qualcosa che potrebbe cambiare n volte (n è il numero di posti in cui usi la query).

    
risposta data 10.10.2013 - 15:14
fonte
2

1) What do you do if you want to switch out ORMs, you would have specific ORM code in your application if you do not contain it in a repository.

Non sono ancora stato in una posizione in cui all'improvviso la società ha deciso di cambiare la tecnologia di accesso ai dati. Se questo dovesse accadere, sarà richiesto del lavoro. Tendo ad astrarre le operazioni di accesso ai dati attraverso le interfacce. Il repository è un modo per risolvere questo problema.

Avrei quindi un altro assembly per l'implementazione concreta del mio livello di accesso ai dati. Ad esempio, potrei avere:

Company.Product.Data e Company.Product.Data.EntityFramework assiemi. Il primo assembly sarebbe utilizzato esclusivamente per le interfacce, mentre un altro sarebbe una implementazione concreta della logica di accesso ai dati di Entity Framework.

2) Is the repository pattern still valid when not using an ORM and you are using ADO.net for data access and populating object data yourself ?

Penso che dipenda da te decidere quale modello è valido o meno. Ho usato un modello di repository nel livello di presentazione. Una cosa da tenere a mente è che alle persone piace buttare responsabilità nei repository. Prima che tu lo sai, il tuo corso di repository ballerà, canterà e farà ogni sorta di cose. Vuoi evitare questo.

Ho visto una classe di repository iniziata con le responsabilità GetAll, GetById, Update ed Delete, che va bene. Quando il progetto fu completato, quella stessa classe aveva dozzine di metodi (responsabilità) che non avrebbero mai dovuto esserci. Ad esempio GetByForename, GetBySurname, UpdateWithExclusions e tutti i tipi di cose pazzesche.

È qui che entrano in gioco query e comandi.

3) If you use an ORM but not the repository pattern where do you keep commonly used queries. Would it be wise to represent each query as a class and have some sort of query factory to create instances ?

Penso che sia una buona idea usare query e comandi al posto dei repository. Faccio quanto segue:

  • Definisci l'interfaccia per una query. Questo ti aiuterà a testare l'unità. Per esempio. public interface IGetProductsByCategoryQuery { ... }

  • Definisci l'implementazione concreta per una query. Sarete in grado di iniettare questi attraverso la cornice IoC di vostra scelta. Per esempio. public class GetProductsByCategoryQuery : IGetProductsByCategoryQuery

Ora invece del repository inquinante con dozzine di responsabilità, raggruppo semplicemente le mie query in namespace. Ad esempio, un'interfaccia per la query sopra potrebbe vivere in: Company.SolutionName.Products.Queries e l'implementazione potrebbe vivere in Company.SolutionName.Products.Queries.Implementation

Per quanto riguarda l'aggiornamento o la rimozione dei dati, utilizzo lo schema di comando nello stesso modo.

Alcuni potrebbero non essere d'accordo e dire che prima che il progetto sia completo, avrai dozzine di classi e spazi dei nomi. Sì lo farai. Nella mia mente è una buona cosa che puoi sfogliare la soluzione in IDE di tua scelta e vedere immediatamente che tipo di responsabilità ha un determinato componente. Se invece hai deciso di utilizzare un pattern di repository, dovrai cercare all'interno di ciascuna classe del repository cercando di risolverne le responsabilità.

    
risposta data 10.10.2013 - 17:12
fonte
1

ESCLUSIONE DI RESPONSABILITÀ: quanto segue si basa sulla mia comprensione e breve esperienza di detto modello (Repository cioè). Potrei sbagliarmi ... anzi, sono abbastanza ottimista che sto sbagliando :) Quindi, mentre questo è un tentativo di risposta, è anche una domanda sotto mentite spoglie.

Sto usando il modello di repository per astrarre il livello di accesso ai dati, che nella maggior parte dei casi è un ORM. È un'interfaccia generica, con metodi per creare, leggere, aggiornare, eliminare e classi di implementazione per LINQ fino a SQL ed EF finora. Potrei realizzare un'implementazione che scrive su file XML su disco (solo un esempio selvaggio di cosa potrei fare con esso). Non sto implementando l'unità di lavoro dal momento che è supportata dagli ORM. Se necessario, potrei probabilmente implementarlo. Mi piace così perché, finora, mi ha dato una bella separazione. Non sto dicendo che non ci sono alternative migliori.

Per rispondere alle tue domande:

  1. Che ti piaccia o no, il cambiamento avverrà. E se hai scritto un sacco di applicazioni e il tempo è arrivato per mantenerle, ma senti che è un dolore lavorare con l'attuale ORM e vuoi cambiarlo, ti loderai per aver fatto una tale astrazione. Usa tutto ciò che ti senti a tuo agio, che si tratti di un deposito o di un altro modello / concetto.
  2. Sì lo è, a patto che lo si usi per separare l'accesso ai dati. Come ho detto prima, puoi realizzare un'implementazione che scrive dati in file flat.
  3. Uso il repository per mantenere le mie query di uso frequente e Oggetti di query per quando ho delle domande che voglio modificare (che non sono così tante).

Per darti un altro esempio, i ragazzi di Umbraco hanno sottratto il contenitore DI, nel caso in cui volessero passare a qualcos'altro.

    
risposta data 10.10.2013 - 16:22
fonte
0

Se l'ORM offre flessibilità di LINQ, caricamento ansioso ecc. Non lo nasconderei dietro alcun livello aggiuntivo.
Se coinvolge raw sql (micro ORM), è necessario utilizzare comunque "metodo per query" per ottenere la riusabilità, rendendo così il pattern di repository adeguato.

What do you do if you want to switch out ORMs? 
You would have ORM specific code in your application if you do not contain it in a repository.

Perché dovresti cambiare?
Dovrebbe essere usato quello che ha la maggior parte delle funzionalità necessarie. È possibile che una nuova versione di ormX porti nuove funzionalità e si rivelerà migliore di quella attuale, ma ...
Se si sceglie di nascondere il dominio, è possibile utilizzare solo le funzionalità che tutti i candidati hanno in comune.
Per esempio. non puoi usare Dictionary<string, Entity> proprietà nelle tue entità perché ormY non può gestirle.

Supponendo che LINQ sia usato, la maggior parte degli switch orm sta semplicemente cambiando i riferimenti di libreria e sostituendo session.Query<Foo>() con context.Foos o simili finché non viene compilato. Compito noioso, ma richiede meno tempo rispetto alla codifica del livello di astrazione.

Is the repository pattern still valid when not using an ORM and you are using ADO.NET for data access and populating object data yourself?

Sì. Il codice dovrebbe essere riutilizzabile e ciò significa mettere sql building, materializzazione degli oggetti ecc. In un unico posto (classe separata). Puoi anche chiamare la classe "XRepository" ed estrarre un'interfaccia da esso.

If you use an ORM but not the repository pattern where do you keep commonly used queries? 
Would it be wise to represent each query as a class and have some sort of query factory to create instances?

Supponendo che LINQ sia usato un wrapper di classe sarebbe un IMHO eccessivo. Un modo migliore sarebbe essere i metodi di estensione

public static IQueryable<T> Published<T>(this IQueryable<T> source) where T : Page
{
    // at some point someone is going to forget to check that status
    // so it makes sense to extract this thing
    return source.Where(x => x.Status == Status.Published && x.PublishTime <= DateTime.UtcNow);
}

Qualsiasi codice che viene utilizzato in più posizioni (o ha il potenziale) ed è abbastanza complicato (soggetto a errori), dovrebbe essere estratto in un posto centralizzato.

    
risposta data 30.12.2013 - 11:51
fonte

Leggi altre domande sui tag