7

Sto cercando di capire come interrogare al meglio un repository.e query con sql raw?

I tre fattori che mi stanno gettando attraverso un ciclo in questo momento sono: Tipo

  1. ritorno dei dati
  2. Colonne per eseguire query
  3. Numero di record per tornare

Punto 1

Per quanto riguarda la ricerca uno:

Ho repository con molti metodi che restituiscono una combinazione di entrambe le entità e valori scalari. Questo sembra portare a "esplosione di metodo". Devo sempre restituire un oggetto Entity? Come dovrei richiedere oggetti per i quali ho solo bisogno di una colonna?

Point 2 Quando si esegue una query dovrei includere ogni colonna della tabella, anche se solo ho bisogno di uno, o due colonne? Se creo query specifiche per questo si porta a più metodi nella repository

punto 3 Come devo fornire le condizioni per la query? Ho letto delle specifiche, ma la mia comprensione è che si collegano i record restituiti e si filtrano quelli che passano in una nuova raccolta. Questo non sembra una buona idea per quanto riguarda le prestazioni. In questo momento ho appena creato un nuovo metodo nel Repo come getNameById() che incapsula la condizione.

Per favore non che io non stia usando un ORM, ho solo raw sql nei miei repository.

Aggiornamento

Punto 1: Sulla base delle risposte e un po 'più ricerca questo sarebbe una buona implementazione?

In questo momento ho un repository di grandi dimensioni che restituisce un mix di oggetti di tipo scalare ed entità (la stessa entità). Sto pensando di poterlo ridurre notevolmente se uso solo un metodo GetUser (userId) e dimentico di scrivere metodi che restituiscono solo valori di colonna singola.

Ad esempio, se è necessario restituire un nome utente, è possibile chiamare il metodo GetUser (userId) che idrata l'oggetto Utente e quindi nel livello di servizio lo si limita a filtrarlo nel nome utente.

Un altro modo sarebbe utilizzare una classe di QueryBuilder che potrei passare nel Repository che potrebbe essere analizzata per generare il corretto sql.

Point 2

Guardando indietro questo è abbastanza simile al punto uno e la mia soluzione attuale sarebbe quello di prendere solo tutti i campi della tabella. È un compromesso tra prestazioni e manutenibilità.

punto 3

avrei bisogno di fornire una sorta di clausola where. Non sono sicuro se questo abbia senso farlo tramite specifica o solo una stringa sql. La mia soluzione attuale è di creare nuovi metodi per questi tipi, ma vorrei qualcosa di più generico per il repository

Nel complesso, continuando a cercare in questo ... Mi piacerebbe sentire più input in questo o collegamenti a libri o riferimenti che legano tutto questo insieme.

+0

Si crea dinamicamente il comando Sql nella classe? – Arian

+0

SQL grezzo e nessun ORM, ha? Come vivere ai margini, vero? Seriamente, perché vuoi gestire raw sql? –

+0

@ yves - baby steps :) – chobo

risposta

3

Ho repository con molti metodi che restituiscono una combinazione di Entità e valori scalari. Questo sembra portare a "esplosione di metodo". Devo sempre restituire un oggetto Entity? Come dovrei richiedere oggetti per i quali ho solo bisogno di una colonna?

È possibile combattere l'esplosione del metodo di repository in modo simile a come si combatteranno altre violazioni SRP. È possibile creare un altro repository per la stessa entità. Vedi questo answer a una domanda simile.

Quando si esegue una query, dovrei includere tutte le colonne della tabella anche se ho solo bisogno di una o due colonne? Se creo query specifiche per questo, si ottengono più metodi nel repository

Questa non è una domanda DDD. Dominio Il design guidato non tratta "righe e colonne". C'è sempre una certa ridondanza nella quantità di dati che carichi per "idratare" l'oggetto dominio, ma devi misurare se questo influisce veramente sulle tue prestazioni. Se questo è davvero un collo di bottiglia per le prestazioni, potrebbe essere un sintomo di un modello di dominio errato.

Come devo fornire le condizioni per la richiesta? Ho letto delle specifiche, ma la mia comprensione è che si collegano i record restituiti e si filtrano quelli che passano in una nuova raccolta. Questo non sembra una buona idea per quanto riguarda le prestazioni. In questo momento ho appena creato un nuovo metodo nel Repo come getNameById() che incapsula la condizione.

Questo è di nuovo un problema di accesso ai dati. Nulla in DDD dice che il tuo repository non può convertire la specifica in una query SQL. Spetta a te decidere se eseguire questa operazione o iterare sui record in memoria (purché il consumatore del repository veda solo la specifica e il repository e non si accorga dell'attuazione effettiva).

Per quanto riguarda "SQL raw rispetto a ORM in DDD", è possibile che questo sia interessante per answer.

+0

Puoi indicare alcune risposte o tutorial che risolvono questo problema di accesso ai dati? – chobo

+0

Il DDD book ha un esempio sulla specifica che viene convertita in SQL raw a causa di considerazioni sulle prestazioni. – Dmitry

+0

È quello blu di Eric Evans? Non sarebbe capitato di conoscere il numero di pagina di quell'esempio?:) – chobo

1

Prima di tutto, non hai davvero spiegato per cosa stai utilizzando tutte queste query. È probabile che sia per le esigenze dell'interfaccia utente. Se è così, non c'è bisogno di passare attraverso tutti questi cerchi (servizio-> repository-> dominio-> dto-> client), basta interrogare il database il più direttamente possibile. E cosa sai, sono finite le domande se puoi interrogare per gli scalari o solo per le colonne di cui hai bisogno. Basta usare plain sql e restituire quello che ti serve. Non creare astrazioni che causano attriti.

+0

Tutto quello che sto cercando è un approccio "best practice" per interrogare i repository quindi non ho un milione di metodi e in qualche modo fattori anche in una discreta performance. – chobo

+0

Iniziare non aggiungendoli al repository in primo luogo se non servono allo scopo del dominio. Spostali su un'altra facciata che rappresenti le query richieste dall'interfaccia utente. Passa velocemente dal cliente alla facciata, dal db alla facciata al cliente. Utilizzare semplici DTO per rappresentare lo stato che deve essere trasportato al client. –

2

Sono d'accordo con tutto ciò che dice Dmitry, ma forse penso che dovresti leggere CQRS.

Ho usato per fare domande simili quando ho iniziato con DDD (riguardo 'metodo esplosione', non i tuoi problemi SQL), e questo mi porta a CQRS.Personalmente, non vedo davvero come DDD sia pratico senza di esso, e risponde a molte di queste domande quando si tratta di interrogare i dati. Usando i suoi principi ciò che suggerirei è:

  1. Utilizzare solo repository di dominio quando si esegue una transazione. Cioè, non usi i repository per visualizzare i dati nell'interfaccia utente. Si recuperano solo gli aggregati dal proprio repository quando si desidera eseguire un'operazione contro di essi.
  2. I repository restituiscono solo gli aggregati, non le singole entità separatamente. Questo ha senso ora dato che stiamo usando i repository solo in senso transazionale, e le entità possono essere mutate solo tramite operazioni atomiche e mantenute dall'aggregato nel suo insieme.
  3. È possibile creare repository separati (o "servizi di query") che forniscono query e tipi di dati personalizzati per qualsiasi dato necessario. Questi possono restituire stupidi DTO senza logica.

Ciò mantiene pulito il repository di dominio appropriato &, fornendo allo stesso tempo i mezzi per creare un sottile strato di accesso ai dati che fornisca query ad alte prestazioni.

Riguardo al modello di specifica: anziché convertirlo in una query SQL nel codice, è possibile fornire proprietà pubbliche sulla specifica che rappresenta i criteri. Questi valori potrebbero quindi essere aggiunti nella clausola where del tuo SQL o inviati come parametri a un SPROC.

1

Chobo,

Abbiamo bisogno di ricordare due cose su repository [Fowler PoEAA] [Evans DDD] modello:

  1. utilizzare un modello Repository come una semplice raccolta. Il repository riassume questi dettagli dell'infrastruttura perché non provengono dal dominio.
  2. Se un repository pattren è una raccolta, è un cluster di oggetti dello stesso tipo.

Altri due tipi possono aiutare il repository: i modelli Query Object [Fowler PoEAA] e Data Mapper [Fowler PoEAA]. I criteri di aggregazione del modello oggetto query utilizzano metodi orientati agli oggetti e sanno come tradurli come un'istruzione SQL. Il pattern Data Mapper conosce mappare gli stati dell'oggetto dall'applicazione e le colonne della tabella dai database.

È possibile utilizzare il modello Lazy Load [Fowler PoEAA] per attenuare il problema degli oggetti di grandi dimensioni in memoria.

Il successo per te!

+0

Penso che l'oggetto Query possa essere di grande aiuto con il problema di interrogare con criteri diversi. Immagino che gli ORM lo abbiano integrato. Grazie per l'elenco di schemi che risolvono questi problemi! – chobo

Problemi correlati