N-layered applicazione di database senza l'utilizzo di un ORM, come fa l'interfaccia utente di specificare che cosa ha bisogno di dati da visualizzare?

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

Domanda

sto cercando puntatori e informazioni qui, farò questo CW in quanto ho il sospetto che non ha alcun sola risposta corretta. Questo è per C #, quindi farò alcuni riferimenti a LINQ qui sotto. Mi scuso anche per il lungo post. Permettetemi di riassumere la questione qui, e allora la domanda completa segue.

Sommario: In un UI / BLL / DAL / DB applicazione 4 strati, come può modifiche all'interfaccia utente, per mostrare più colonne (ad esempio in una griglia), evitare perdite attraverso lo strato logica di business e nel foro di dati strato, per entrare in possesso dei dati per visualizzare (ammesso che sia già presente nel database).


Supponiamo che un'applicazione a strati con 3 (4) Strati:

  • Interfaccia utente (UI)
  • Business Logic Layer (BLL)
  • Data Access Layer (DAL)
  • Database (DB; il 4 ° livello)

In questo caso, il DAL è responsabile per la costruzione di istruzioni SQL e li esegue sul database, restituzione dei dati.

E 'l'unico modo per "correttamente" la costruzione di un tale strato di fare proprio sempre "select *"? Per me questo è un grande no-no, ma mi permetta di spiegare il motivo per cui mi sto chiedendo.

Diciamo che voglio, per la mia interfaccia utente, per visualizzare tutti i dipendenti che hanno un record attivo dell'occupazione. Con il termine "attivo" Voglio dire che i record di occupazione da-to date contiene oggi (o forse anche una data posso impostare nell'interfaccia utente).

In questo caso, diciamo che voglio inviare una e-mail a tutte quelle persone, quindi ho un po 'di codice nel BLL che assicura non ho già inviato e-mail alle stesse persone già, ecc.

Per la BLL, ha bisogno di minime quantità di dati. Forse richiama lo strato di accesso ai dati per ottenere che la lista dei dipendenti attivi, e poi una chiamata per ottenere un elenco dei messaggi di posta elettronica che ha inviati. Poi si unisce su quelli e costruisce un nuovo elenco. Forse questo potrebbe essere fatto con l'aiuto dello strato di accesso ai dati, questo non è importante.

Quello che è importante è che per il livello di business, non c'è davvero più dati di cui ha bisogno. Forse ha solo bisogno l'identificatore univoco per ogni dipendente, per entrambi gli elenchi, per abbinare al momento, e poi dire "Queste sono le identificatori univoci di coloro che sono attivi, che non è stato già inviato una e-mail a". Ho poi costruisco il codice DAL che costruisce istruzioni SQL che recupera solo ciò che le esigenze strato di business? Vale a dire. basta "SELECT id FROM WHERE dipendenti ..."?

Cosa devo fare allora per l'interfaccia utente? Per l'utente, forse sarebbe meglio includere molte più informazioni, a seconda del perché voglio inviare email. Per esempio, potrei voler includere alcune informazioni rudimentali di contatto, o il reparto per cui lavorano, o il loro nome manager, ecc, per non dire che io almeno nome e l'indirizzo e-mail le informazioni da visualizzare.

In che modo l'interfaccia utente ottenere che i dati? Faccio a cambiare il DAL per assicurarsi che torno abbastanza dati torna alla UI? Faccio a cambiare il BLL per assicurarsi che restituisce dati sufficienti per l'interfaccia utente? Se le strutture di oggetti o di dati restituiti dal DAL indietro al BLL possono essere inviati all'interfaccia utente pure, forse il BLL non ha bisogno molto di un cambiamento, ma poi esigenze degli impatti UI uno strato di là di quanto deve comunicare . E se i due mondi operano su diverse strutture di dati, le modifiche avrebbero probabilmente essere fatto per entrambe le cose.

E che poi, quando l'interfaccia utente è cambiata, per aiutare l'utente ancora di più, con l'aggiunta di più colonne, quanto profondo avrei / dovrei andare al fine di modificare l'interfaccia utente? (Supponendo che i dati sono presenti nel database già così nessun cambiamento è necessaria lì.)

Un suggerimento che ha messo a punto è quello di usare LINQ to SQL e IQueryable, in modo che se il DAL, che si occupa di ciò che (come in quali tipi di dati) e il motivo per cui (come in Where-clausole) ha restituito IQueryables, BLL potrebbe potenzialmente ritorno quelle fino all'interfaccia utente, che potrebbe quindi costruire una Linq query che recupera i dati necessari. Il codice interfaccia utente potrebbe quindi tirare nelle colonne di cui ha bisogno. Questo sarebbe work poiché con IQuerables, l'interfaccia utente finirebbe in realtà l'esecuzione della query, e potrebbe quindi utilizzare "selezionare nuova {X, Y, Z}" per specificare che cosa ha bisogno, e anche unirsi in altre tabelle, se necessario.

Questo sembra disordinato a me. Che l'interfaccia utente esegue il codice SQL in sé, anche se è stata nascosta dietro un frontend Linq.

Ma, perché questo avvenga, il BLL o il DAL non dovrebbe essere consentito di chiudere le connessioni al database, e in un tipo IOC del mondo, il DAL-service potrebbe avere smaltito un po 'prima di quanto il codice utente vorrebbe , in modo che query LINQ potrebbe anche finire con l'eccezione "Impossibile accedere a un oggetto eliminato".

Quindi sono alla ricerca per i puntatori. Quanto lontani siamo? Come stai che fare con questo? Considero il fatto che cambia per l'interfaccia utente perderà attraverso la BLL e DAL in una pessima soluzione, ma in questo momento non sembra che possiamo fare meglio.

Ti prego, dimmi quanto stupido siamo e dimostrare che mi sbaglio?

E si noti che questo è un sistema legacy. Modificare lo schema del database non è nel campo di applicazione per anni ancora, quindi una soluzione per utilizzare gli oggetti ORM che essenzialmente fare l'equivalente di "selezionare *" non è davvero un'opzione. Abbiamo alcune tabelle di grandi dimensioni che vorremmo evitare di tirare attraverso l'intero elenco dei livelli.

È stato utile?

Soluzione

Utilizzare il concetto di un modello di vista (o oggetto di trasferimento dati) che sono casi consumo UI. Sarà compito del BLL a prendere questi oggetti e se i dati sono incompleti, richiesta dati aggiuntivi (che noi chiamiamo modello). Poi il BLL può prendere decisioni corrette su quali modelli di vista per tornare. Non lasciate che il vostro modello (dati) specifics permeano per l'interfaccia utente.

UI <-- (viewmodel) ---> BLL <-- (model) --> Peristence/Data layers

Questo disaccoppiamento consente di scalare voi l'applicazione migliore. L'indipendenza persistenza Penso appena naturalmente cade fuori di questo approccio, come la costruzione e le specifiche dei modelli vista potrebbe fare in modo flessibile nel BLL utilizzando linq2ql o un'altra tecnologia ORM.

Altri suggerimenti

Questo non è affatto un problema facile da risolvere. Ho visto molti tentativi (tra cui l'approccio IQueryable che descrivi), ma nessuno che sono perfetti. Purtroppo siamo ancora in attesa per la soluzione perfetta. Fino ad allora, dovremo fare che fare con l'imperfezione.

Sono completamente d'accordo che riguarda DAL non dovrebbe essere consentito di fuoriuscire attraverso a strati superiori, quindi un BLL isolante è necessario.

Anche se non si ha il lusso di ridefinire la tecnologia di accesso ai dati nel progetto corrente, aiuta ancora di pensare al modello di dominio in termini di persistenza ignoranza. Un corrolary della Persistenza ignoranza è che ogni oggetto di dominio è un'unità autonoma che non ha alcuna nozione di roba come colonne del database. È meglio rispettare integretiy dati come invarianti in tali oggetti, ma ciò significa anche che un oggetto Dominio esemplificato avrà tutte dati costitutivi caricati. Si tratta di un aut-aut proposizione, così la chiave diventa di trovare un buon modello di dominio che assicura che ogni oggetto attesa di dominio (e deve essere caricato con) un importo 'appropriata' di dati.

oggetti Troppo granulari possono portare a interfacce DAL chiacchierone, ma anche gli oggetti grossolani possono portare a dati troppo irrilevanti corso di caricamento.

Un esercizio molto importante è quello di analizzare e modellare Aggregati del modello di dominio in modo che il giusto equilibrio in modo corretto. Il libro Domain-Driven Design contiene alcune analisi molto illuminanti di aggregati di modellazione.

Un'altra strategia che può essere utile a questo proposito è quello di cercare di applicare il principio di Hollywood, per quanto possibile. Il problema principale che si descrive riguarda query, ma se si può spostare l'attenzione ad essere più Comando-oriented, si può essere in grado di definire alcune interfacce più a grana grossa, che non fa richiedono di caricare sempre troppi dati.

Io non sono a conoscenza di alcuna soluzione semplice a questa sfida. Ci sono tecniche come quelli che ho descritto sopra che possono aiutare a risolvere alcuni dei problemi, ma alla fine è ancora un'arte che richiede esperienza, l'abilità e la disciplina.

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