Modello di repository vs DAL


93

Sono la stessa cosa? Ho appena finito di guardare il tutorial di Rob Connery Storefront e sembrano essere tecniche simili. Voglio dire, quando implemento un oggetto DAL ho i metodi GetStuff, Add / Delete ecc e scrivo sempre prima l'interfaccia in modo da poter cambiare db in seguito.

Sto confondendo le cose?

Risposte:


88

Sicuramente non sei tu quello che confonde le cose. :-)

Penso che la risposta alla domanda dipenda da quanto purista vuoi essere.

Se vuoi un punto di vista DDD rigoroso, questo ti porterà su una strada. Se guardi al repository come a uno schema che ci ha aiutato a standardizzare l'interfaccia del livello che separa tra i servizi e il database, ne verrai abbattuto un altro.

Il repository dal mio punto di vista è solo un livello di accesso ai dati chiaramente specificato, o in altre parole un modo standardizzato per implementare il tuo livello di accesso ai dati. Ci sono alcune differenze tra le diverse implementazioni del repository, ma il concetto è lo stesso.

Alcune persone metteranno più vincoli DDD sul repository mentre altri useranno il repository come un comodo mediatore tra il database e il livello di servizio. Un repository come un DAL isola il livello di servizio dalle specifiche di accesso ai dati.

Un problema di implementazione che sembra renderli diversi è che un repository viene spesso creato con metodi che accettano una specifica. Il repository restituirà dati che soddisfano tale specifica. La maggior parte dei DAL tradizionali che ho visto avrà un set più ampio di metodi in cui il metodo prenderà un numero qualsiasi di parametri. Anche se questa può sembrare una piccola differenza, è un grosso problema quando si entra nei regni di Linq ed Expressions. La nostra interfaccia di repository predefinita è simile a questa:

public interface IRepository : IDisposable
{
    T[] GetAll<T>();
    T[] GetAll<T>(Expression<Func<T, bool>> filter);
    T GetSingle<T>(Expression<Func<T, bool>> filter);
    T GetSingle<T>(Expression<Func<T, bool>> filter, List<Expression<Func<T, object>>> subSelectors);
    void Delete<T>(T entity);
    void Add<T>(T entity);
    int SaveChanges();
    DbTransaction BeginTransaction();
}

È un DAL o un repository? In questo caso credo sia entrambe le cose.

Kim


5
In ritardo alla festa qui, ma perché T [], non List <T> (o simili)?
Mike Kingscott,

27
Forse IEnumerable <T> sarebbe il migliore.
Venemo

9
o IQueryable <T>
kenwarner

1
Penso che IQueryable <T> sarebbe la scelta migliore, perché ti consente di concatenare metodi e differire l'esecuzione lasciando che il database faccia tutto il lavoro.
0lukasz0

4
@kenwarner Penso che la restituzione di IQueryable <T> lasci trapelare l'astrazione. Dovresti restituire gli oggetti di dominio dal tuo repository.
Matteo

42

Un repository è un modello che può essere applicato in molti modi diversi, mentre il livello di accesso ai dati ha una responsabilità molto chiara: il DAL deve sapere come connettersi al tuo archivio dati per eseguire operazioni CRUD.

Un repository può essere un DAL, ma può anche trovarsi di fronte al DAL e fungere da ponte tra il livello degli oggetti di business e il livello dei dati. L'implementazione utilizzata varierà da progetto a progetto.


23

Una grande differenza è che un DAO è un modo generico per gestire la persistenza per qualsiasi entità nel tuo dominio. Un repository d'altra parte si occupa solo di radici aggregate.


26
La prima cosa da capire è che un repository come modello fa parte del sistema più ampio noto come Domain Driven Design. In DDD gli oggetti di dominio sono raggruppati in aggregati, ciascuno con una radice aggregata. Ad esempio, PurchaseOrder è una radice aggregata e OrderItems sono elementi secondari all'interno della radice aggregata. Un repository si occupa solo di root aggregate. Cioè, un OrderItem, ad esempio, non viene mai caricato indipendentemente dalla sua radice aggregata. Quindi, non avresti mai un repository OrderItem in DDD. Tuttavia, in un sistema non DDD potresti avere un OrderItemDao poiché Dao non è limitato alle radici aggregate.
pondermatic

NG, grazie! Avevo iniziato a vederlo in quel modo, ma questo lo rende chiaro. Dovrò iniziare a leggere tutta la letteratura DDD!
David

@bingle, ottima descrizione delle radici aggregate e di come gli oggetti figli vengono caricati da un repository. Dove esisterebbe un repository in un'applicazione a più livelli? Potrei vederlo essere in una libreria del livello di accesso ai dati ma poiché carica oggetti figlio, dovrebbe invece esistere nella libreria del livello logico? Il mio istinto mi dice il livello di accesso ai dati ma volevo la tua opinione in merito.
Jeff LaFay

12

Stavo cercando una risposta a una domanda simile e sono d'accordo con le due risposte con il punteggio più alto. Cercando di chiarire questo punto per me stesso, ho scoperto che se le specifiche, che vanno di pari passo con il pattern Repository, vengono implementate come membri di prima classe del modello di dominio, allora posso

  • riutilizzare le definizioni delle specifiche con parametri diversi,
  • manipolare i parametri delle istanze di specifica esistenti (ad esempio per specializzarsi),
  • combinali ,
  • eseguire la logica di business su di essi senza dover mai accedere al database,
  • e, naturalmente, testarli in unità indipendentemente dalle implementazioni effettive del repository.

Potrei anche spingermi così lontano e affermare che, a meno che il pattern Repository non venga utilizzato insieme al pattern Specification, non è realmente "Repository", ma un DAL. Un esempio artificioso in pseudo-codice:

specification100 = new AccountHasMoreOrdersThan(100)
specification200 = new AccountHasMoreOrdersThan(200)

assert that specification200.isSpecialCaseOf(specification100)

specificationAge = new AccountIsOlderThan('2000-01-01')

combinedSpec = new CompositeSpecification(
    SpecificationOperator.And, specification200, specificationAge)

for each account in Repository<Account>.GetAllSatisfying(combinedSpec)
    assert that account.Created < '2000-01-01'
    assert that account.Orders.Count > 200

Vedi il Saggio delle specifiche di Fowler per i dettagli (questo è ciò su cui ho basato quanto sopra).

Un DAL avrebbe metodi specializzati come

IoCManager.InstanceFor<IAccountDAO>()
    .GetAccountsWithAtLeastOrdersAndCreatedBefore(200, '2000-01-01')

Puoi vedere come questo può diventare rapidamente complicato, soprattutto perché devi definire ciascuna delle interfacce DAL / DAO con questo approccio e implementare il metodo di query DAL.

In .NET, le query LINQ possono essere un modo per implementare le specifiche, ma la combinazione delle specifiche (espressioni) potrebbe non essere agevole come con una soluzione sviluppata internamente. Alcune idee per questo sono descritte in questa domanda SO .


2

La mia opinione personale è che si tratti di mappatura, vedere: http://www.martinfowler.com/eaaCatalog/repository.html . Quindi l'output / input dal repository sono oggetti di dominio, che sul DAL potrebbero essere qualsiasi cosa. Per me questa è un'aggiunta / restrizione importante, poiché puoi aggiungere un'implementazione del repository per un database / servizio / qualsiasi cosa con un layout diverso e hai un posto chiaro in cui concentrarti sulla mappatura. Se non dovessi utilizzare tale restrizione e avere la mappatura altrove, avere modi diversi per rappresentare i dati può influire sul codice in punti in cui non dovrebbe cambiare.


1

Si tratta di interpretazione e contesto. Possono essere molto simili o addirittura molto diversi, ma finché la soluzione funziona, cosa c'è in un nome!


1

Il repository è un pattern, questo è un modo per implementare le cose in modo standardizzato per riutilizzare il codice come possiamo.


1

Il vantaggio dell'utilizzo del modello di repository consiste nel simulare il livello di accesso ai dati, in modo da poter testare il codice del livello aziendale senza chiamare il codice DAL. Ci sono altri grandi vantaggi, ma questo sembra essere molto vitale per me.


1
Puoi ancora deridere un DAL, non è necessario che sia un repository di per sé. Il punto importante è che qualunque strategia di accesso ai dati si utilizzi dovrebbe implementare un'interfaccia. Ciò ti consentirà di utilizzare i contenitori IoC e di testare in modo accurato il tuo codice aziendale senza bisogno di un archivio dati.
cdaq

0

Da quello che ho capito possono significare fondamentalmente la stessa cosa, ma la denominazione varia in base al contesto.

Ad esempio, potresti avere una classe Dal / Dao che implementa un'interfaccia IRepository.

Dal / Dao è un termine del livello dati; i livelli più alti della tua applicazione pensano in termini di repository.


0

Quindi nella maggior parte dei casi (semplici) DAO è un'implementazione di Repository?

Per quanto ho capito, sembra che DAO si occupi proprio dell'accesso al db (CRUD - No seleziona però ?!) mentre Repository consente di astrarre l'intero accesso ai dati, forse essendo una facciata per più DAO (forse diverse fonti di dati).

Sono sulla strada giusta?


In realtà, lo invertirei e direi che da un punto di vista semplicistico, un repository è uno stile di implementazione particolare per un DAO, ma sì, sei sulla strada giusta. (R da CRUD = Leggi, quindi questa è la tua scelta.)
Jeromy Irvine

0

Nel mondo esterno (cioè codice client) il repository è lo stesso di DAL, tranne:

(1) i suoi metodi di inserimento / aggiornamento / eliminazione sono limitati per avere l'oggetto contenitore di dati come parametro.

(2) per l'operazione di lettura può richiedere una specifica semplice come un DAL (ad esempio GetByPK) o una specifica avanzata.

Internamente funziona con un Data Mapper Layer (per esempio il contesto del framework dell'entità ecc.) Per eseguire l'effettiva operazione CRUD.

Cosa non significa modello di repository: -

Inoltre, ho visto le persone spesso confondersi nell'avere un metodo Save separato come implementazione di esempio del pattern di repository oltre ai metodi Insert / Update / Delete che salva tutte le modifiche in memoria eseguite dai metodi di inserimento / aggiornamento / eliminazione nel database. Possiamo avere un metodo di salvataggio sicuramente in un repository, ma non è responsabilità del repository isolare CUD in memoria (Crea, Aggiorna, Elimina) e metodi di persistenza (che esegue l'effettiva operazione di scrittura / modifica nel database), ma il responsabilità del modello di unità di lavoro.

Spero che questo ti aiuti!


0

Si potrebbe sostenere che un "repository" è una classe specifica e un "DAL" è l'intero livello costituito da repository, DTO, classi di utilità e qualsiasi altra cosa richiesta.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.