Questa è la situazione:
Supponiamo di avere un'applicazione in cui esistono due tipi di entità:
Company
Person
Inoltre, la Person
ha un riferimento alla Company
tramite Person.employer
, che indica la società a cui è assunta una persona.
Nella mia applicazione sto usando i repository di separare le operazioni di database dai miei servizi connessi alle imprese-modello: Ho un PersonRepository.findOne(id)
metodo per recuperare una Person
un'entità e una CompanyRepository.findOne(id)
metodo per recuperare una Company
. Fin qui tutto bene.
Questo è il dilemma:
Ora, se faccio una chiamata a PersonRepository.findOne(id)
a prendere una Person
entità, ho anche bisogno di avere una completamente risolto Company
incluse in linea tramite il Person.employer
proprietà â € “e questo è dove sto affrontando il dilemma di dover due opzioni di implementazione che sono entrambe subottimali:
Opzione A) Query ridondanti nei miei repository ma meno round trip del database:
All'interno del PersonRepository
posso creare una query che seleziona l'utente e seleziona l'azienda in una singola query, tuttavia l'espressione select
per l'azienda è difficile e include alcuni join per assemblare correttamente l'azienda. Il CompanyRepository
contiene già questa logica per select
la società e riscriverla nel UserRepository
è ridondante. Quindi, idealmente, desidero solo che il CompanyRepository
aziendale si occupi della logica di selezione dell'azienda per evitare di dover codificare la stessa espressione di query in modo ridondante in due repository.
Opzione B): separazione delle preoccupazioni senza ridondanza del codice di interrogazione ma al prezzo di ulteriori db roundtrip e repo-dependencies:
All'interno del PersonRepository
potrei fare riferimento al CompanyRepository
per occuparsi del recupero dell'oggetto Company
e quindi aggiungere questa entità alla proprietà Person.employer
nel PersonRepository
. In questo modo, ho mantenuto la logica di interrogare la società incapsulata all'interno del CompanyRepository
aziendale con la quale si ottiene una netta separazione delle preoccupazioni. Lo svantaggio di questo è che effettuo ulteriori round trip nel database poiché due query separate sono eseguite da due repository.
Quindi, in generale, qual è il modo preferito per affrontare questo dilemma?
Inoltre, qual è il modo preferito per gestire questa situazione in ASP.NET Core ed EF Core?
Modifica: per evitare risposte basate sull'opinione Voglio sottolineare: non sto cercando un pro e contro delle due opzioni presentate sopra, ma piuttosto di cercare una soluzione che integri le parti buone di entrambe le opzioni - perché forse sono solo su la traccia sbagliata qui con le mie due opzioni elencate. Sto anche bene con una risposta che spiega perché non esiste una tale soluzione integrativa, così posso dormire meglio e andare avanti.
Per recuperare una società per ID è necessario leggere i dati della Person
e recuperare da essa l'ID della società. Quindi, se si desidera mantenere la logica di query aziendale in un unico luogo, si otterrebbero due viaggi di andata e ritorno: uno per ottenere l'ID dell'azienda (insieme a qualsiasi altro attributo di una Person
) e uno per ottenere l'azienda stessa.
È possibile riutilizzare il codice che rende un'azienda da DbDataReader
, ma la query persona + società presumibilmente richiederebbe l'unione per "inoltrare" l' companyId
della persona alla query Company
, quindi il testo di queste query dovrebbe essere diverso.
Si può avere in entrambi i modi (un roundtrip, senza query ripetute) se si sposta la logica di interrogazione in stored procedure. In questo modo il tuo person_sp
eseguirà company_sp
e ti restituirà tutti i dati rilevanti. Se necessario, il tuo codice C # potrebbe raccogliere reader.NextResult()
risultati reader.NextResult()
usando reader.NextResult()
. Ora il "trasferimento" dell'ID aziendale avverrebbe sul lato RDBMS, eliminando il secondo round trip. Tuttavia, questo approccio richiederebbe la conservazione di stored procedure sul lato RDBMS, in pratica la spedizione di alcune logiche di repository dalla base del codice C #.