2011-01-03 10 views
19

Per molto tempo ho utilizzato AutoMapper per associare i miei modelli di dominio ai miei DTO e per mappare il DTO ai modelli di dominio.Modello di progettazione per la mappatura di DTO contenenti raccolte secondarie sui modelli di dominio

Sto usando EF4 per il mio ORM e questa mappatura diventa davvero brutta quando il modello che si sta mappando contiene collezioni figlio che devono essere aggiunte/aggiornate/rimosse da. Mentre proseguo con il mio progetto continuo a correre questo problema sempre di più: foto per un post di blog, pacchetti per un ordine, ecc.

Quando si passa da DTO-> modello di dominio, finisco per dover aggiungere un Chiamata BeforeMap che rimuove tutte le entità dalla collezione del modello di dominio e quindi aggiunge un valore ValueResolver personalizzato per la raccolta che preleva il PK di ogni entità dal DTO, lo acquisisce dal DB (in modo che Entity Framework non ritenga di aggiungere una nuova entità) e la aggiunge nuovamente alla raccolta del modello di dominio e quindi applica eventuali aggiornamenti ai singoli campi.

Questa è una soluzione davvero brutta, ma lo sono anche i miei tentativi di gestire manualmente l'aggiornamento di queste raccolte. Qualcuno ha qualche suggerimento per un approccio più pulito?

+0

L'utilizzo di Automapper per mappare i modelli di dominio probabilmente significa che non si utilizza Domain Driven Design. Sto solo dicendo – jfar

+1

Non è realistico per me voler gestire questa mappatura in modo pulito usando una soluzione di mappatura auto-magica? Dovrei invece creare un servizio esclusivamente per l'aggiornamento dei miei modelli di dominio dai miei DTO? – inolen

+0

@jfar come capisci? Innanzitutto, un modello di dominio non è sinonimo di DDD. Implicando che i modelli di dominio non dovrebbero essere mappati, la mano sventolando come "non utilizza Domain Driven Design", e non fornendo alcuna ulteriore spiegazione non sembra molto utile, vero? In un'architettura a livelli non è raro trovare un livello di servizio che si trova sopra il modello di dominio. Inoltre, non è raro che il livello di servizio comunichi con il dominio, l'interfaccia utente e altri livelli tramite un oggetto di trasferimento, contribuendo a mantenere una "linea luminosa" tra questi livelli. – nerraga

risposta

3

È possibile utilizzare ValueInjecter anziché AutoMapper per questa funzionalità. Dai un'occhiata a questa domanda dove i produttori di entrambi pesano, AutoMapper vs ValueInjecter. Non ho usato personalmente Value Injecter, ma è stato creato per fare ciò che stai cercando di fare.AutoMapper è migliore per l'appiattimento, ma l'autore di AutoMapper ammette che non è un buon strumento per "Unflattening", che è ciò che stai cercando di fare.

1

A causa dell'esperienza molto brutta con l'aggiornamento del grafico degli oggetti scollegati, carico sempre prima il grafico dell'oggetto reale dal database e unisco manualmente il mio DTO in questo grafico dell'oggetto. Di solito finisco con diverse classi di helper di fusione con metodi che uniscono DTO (o modelli di visualizzazione) agli oggetti Dominio. Sto anche cercando una soluzione migliore.

Ho anche provato una soluzione in cui non ho caricato prima il grafico degli oggetti dal database. Invece ho usato adattatori personalizzati per creare un grafico di oggetti di dominio separati, collegato al contesto e impostato stati di tutti gli oggetti e le relazioni. Ma era un modo sbagliato ed estremamente complesso che non poteva essere usato per tutti gli scenari (la combinazione di aggiornamenti e inserimenti di subentities non poteva essere gestita senza ulteriori dati trasferiti sullo stato iniziale).

+0

È bello sapere che non sono solo. Mi sento davvero male riferendomi al mio repository concreto nel mio AutoMapper, tuttavia, non ho il desiderio di iniziare a utilizzare l'IoC solo per testare quelle unità (in genere prendo i repository come parametri del costruttore). I casi complessi possono creare queste classi di servizio solo per unire nuovamente le DTO, e suppongo che continui ad usare AutoMapper per i casi semplici, ma sembra anche debole. Mi piacerebbe trovare un modello di progettazione coerente da utilizzare su tutta la linea. – inolen

+0

Sembra che il progetto su cui sto lavorando utilizzi il tuo secondo metodo, ma siamo a un punto in cui sembra che dovremo passare all'interrogazione di tutte le entità separate prima di caricare valori dai nostri DTO. Sono contraria perché "sembra sbagliato", perché dovrei aver bisogno di eseguire una query prima di eseguire un aggiornamento? Mi chiedo se una forma estesa di Lazy Loading mi permetta di segnalare al dominio quali proprietà sulle mie entità non sono state impostate dal mio DTO e recuperarle dal DB se necessario. Potrei usare questo modello T4, ma ancora una volta mi sembra di scrivere Entity Framework per Microsoft ... –

1

In Hibernate c'è un'opzione in cascata in cui gli aggiornamenti da ai bambini ..

penso NHibernate ha una simile opzione cascadeAll.

0

Se è possibile eseguire il relay presupponendo che la raccolta figlio del DTO sia la probabilmente la versione più aggiornata, è possibile sostituire la vecchia collezione con quella nuova.

Abbiamo avuto lo stesso problema con NHibernate e abbiamo risolto in questo modo:

  1. Usa ConstructWith per tirare l'entità fuori dal database utilizzando l'id del dto.
  2. Utilizzare BeforeMap per CANCELLARE l'intera raccolta figlio (assicurarsi che il riferimento sul figlio sia impostato su null).
  3. AutoMapper copia automaticamente la nuova raccolta.

Fortunatamente, NHibernate è stato abbastanza intelligente da applicare solo le modifiche, non posso dire se EF fa lo stesso. Questa non è una soluzione perfetta, ma funziona per un semplice modello di dominio.

Problemi correlati