Come viene Comando Query Separation (CQS) implementata quando si utilizza un ORM?

StackOverflow https://stackoverflow.com/questions/1295686

  •  18-09-2019
  •  | 
  •  

Domanda

Il principio alla base del pattern architetturale CQS è quello di separare le vostre domande e comandi in percorsi distinti. Idealmente, il tuo negozio di persistenza si può leggere / scrivere partizionato, ma nel mio caso, v'è un unico database normalizzato.

Se si sta usando un ORM (NHibernate nel mio caso), è chiaro che l'ORM viene utilizzato quando l'emissione di comandi. Ma che dire di tutte le varie query è necessario eseguire per modellare i dati (DTOs) per gli schermi degli utenti, è pratica comune di abbandonare l'ORM quando si fa il lato di query di CQS?

Dove dovrei implementare le mie domande e le proiezioni DTO? ADO.NET dritto (DataReaders, DTOS, DataTable, stored procedure)? Alcune query sono abbastanza unico e coinvolgere un sacco di join per tirare tutto insieme. Io non voglio denormalizzare il database per le query, ma ho potuto creare viste (denormalizzazione poveri).

È stato utile?

Soluzione

Sto assumendo da CQS si intende il modello architettonico DDD alias CQRS , non strettamente il CQS principio.

Mi piacerebbe ancora utilizzare NHibernate per la vostra lettura solo modello. Ci sono molti vantaggi, come futuri e multi query, pigro / eager loading ecc ... che ottimizzano DB chattiness. Inoltre, sarà più facile per comporre le query con un ORM, se l'interfaccia utente consente all'utente di modificare sostanzialmente la clausola where.

Per quanto riguarda come gestire tecnicamente un unico modello lettura, è possibile contrassegnare un immutabile con NHibernate. Si potrebbe semplicemente marcare tutte le entità del modello di lettura immutabile. Inoltre, non credo che è possibile aggiornare le proiezioni in NHibernate in modo che è un'altra opzione di andare per la vostra lettura unico modello (Qualcuno per favore correggetemi se sbaglio come sono sicuro al 100%).

Per quanto riguarda le mappature NH brutte o impossibili: NH può mappare viste e stored procedure, quindi penso che sarebbe bene utilizzare questi quando è necessario. Le viste sono probabilmente un po 'più flessibile di stored procedure per uno scenario di sola lettura, perché il vostro SQL sarà ancora dinamico. Tuttavia, se avete bisogno di lettura / scrittura per qualsiasi di queste strutture appiattite avrei mappa per una procedura di memorizzazione.

Altri suggerimenti

In definitiva, l'idea è che si dovrebbe usare qualunque rende il canale di query più facile per voi per costruire e mantenere. Non è più preoccuparsi di aggiornamenti, far rispettare le regole di business, mantenendo l'integrità dei dati, o anche la movimentazione del carico (per la maggior parte). Quindi sei libero di scegliere molte opzioni che in precedenza non erano sul tavolo.

Ma NHibernate può ancora essere una buona opzione ... è solo non è più il default automatica (che a volte è per il lato di comando).

Abbiamo scelto di utilizzare Castello Active Record (che si basa sulla NHibernate sotto il cofano), soprattutto perché ha una caratteristica piacevole che genererà un tavolo per voi da una classe. Questo si adatta ottimamente per noi, perché qui c'è il nostro flusso di lavoro: In primo luogo, creiamo una classe ViewModel. Questa classe è modellato interamente per le esigenze della vista. Poi, vi segnalo che ViewModel con il castello di attributi di Active Record. Poi, chiediamo attivo Record per generare la tabella corrispondente per quella classe nel database Query. Questo è il modo più veloce, più liscia che abbiamo trovato per ottenere rapidamente una tabella di database Query che serve la classe ViewModel. La generazione automatica riflette la realtà che l'unico motivo esiste la tabella deve servire la vista.

Stiamo usando EF per la parte di comando, e ADO.NET dritti => DTOs per la catena di query. Vantaggi:

1) Possibilità di ottimizzare le query SQL e utilizzare negozio avanzata DB caratteristiche non astratta nello strato ORM

Meno 2) spese generali

Ma stiamo usando la separazione solo per esigenti parti (di ricerca), il resto si basa sulla comune modello di Entity Framework.

Non c'è la necessità di utilizzare un approccio diverso alla lettura del database contro l'aggiornamento del database. CQS afferma semplicemente che comanda che aggiornare l'archivio di dati dovrebbe essere separata dalle query che leggono lo stato dall'archivio dati.

È comunque possibile utilizzare NHibernate per leggere dal vostro archivio dati, ma si potrebbe desiderare di rendere evidente con la creazione di due classi diverse di incapsulare l'accesso dati. Una classe avrebbe metodi per leggere (query) l'archivio dati, l'altra classe avrebbe metodi per emettere comandi (aggiungere, aggiornare, cancellare) a l'archivio dati.

Quello che si sta cercando di evitare è un metodo che riceve un messaggio dal database, e poi segna il messaggio come letto nel database. Questo dovrebbe essere due distinte chiamate di metodo. Si consiglia di non modificare lo stato e restituire un valore dallo stesso metodo.

Mi piace tenere di ORM separato per legge e scrive quindi vorrei usare (e uso):

NHibernate per i comandi - mappe splendidamente il mio modello di dominio

Dapper.net per le query - splendidamente mie mappe DTO e permette felxibility se la query è troppo complessa

.

Sono una coppia perfetta, proprio come Han Solo e Chewbacca.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top