8

Mam następujący model domeny:Czy DTO mają zagnieżdżone DTO?

public class Playlist 
{ 
    public long Id { get; set; } 
    public string Title { get; set; } 
    public virtual ICollection<Song> Songs { get; set; } 
} 

public class Song 
{ 
    public long Id { get; set; } 
    public string Name { get; set; } 
    public virtual Playlist Playlist { get; set; } 
    public virtual ICollection<Catalog> Matches { get; set; } 
} 

public class Catalog 
{ 
    public long Id { get; set; } 
    public string Title { get; set; } 
} 

Moja usługa ma następujący kod:

public PlaylistResult FindByPlaylistId(long id) 
{ 
    Playlist playlist = playlistRepository.GetById(id); 

    foreach (var song in playlist.Songs) 
    { 
     song.Matches = catalogRepository.GetMatches(song.Name).ToList(); 
    } 

    return new PlaylistResult(new PlaylistDTO(playlist), playlist.Songs.Select(x => new SongDTO(x))); 
} 

Moje usługi pobiera listę odtwarzania i piosenek z bazy danych, a następnie dla każdego utworu z listy odtwarzania nie odpala zapytanie, aby uzyskać dodatkowe dopasowania z bazy danych (przy użyciu pełnego wyszukiwania tekstu SQL Server) specyficzne dla tej piosenki.

Dane są następnie konwertowane na DTO, dodawane do obiektu wyniku i przekazywane z powrotem do kontrolera. Kod wygląda następująco:

public class PlaylistResult 
{ 
    public PlaylistResult(PlaylistDTO playlist, IEnumerable<SongDTO> songs) 
    { 
     Playlist = playlist; 
     Songs = songs; 
    } 

    public PlaylistDTO Playlist { get; private set; } 

    public IEnumerable<SongDTO> Songs { get; private set; } 
} 

Problem:

Przedmiotem PlaylistResult pracował wielki do tej pory, ale niedawne wprowadzenie meczów dokonał rzeczy nieco bardziej skomplikowane. Wygląda na to, że nie mają innego wyboru niż do modyfikowania moja SongDTO wziąć pod uwagę meczów i wyglądać tak:

public class SongDTO 
{ 
    public SongDTO(Song song, IEnumerable<CatalogDTO> matches) 
    { 
     Id = song.Id; 
     Name = song.Name; 
     Matches = matches; 
    } 

    public long Id { get; private set; } 

    public string Name { get; private set; } 

    public IEnumerable<CatalogDTO> Matches { get; private set; } 
} 

Ale to nie narusza cel DTO'S? Rozumiem, że DTO są spłaszczoną reprezentacją danych i to podejście nie jest spłaszczone. Z drugiej strony, nie widzę, jak to zrobić, ponieważ każdy mecz jest charakterystyczny dla każdej piosenki.

Jestem świadomy, że mógłbym ułatwić to sobie i wyrzucić DTO i przekazać model domeny bezpośrednio do kontrolera i nazwać to dziennie. Ale nie chcę tego robić, ponieważ celem jest nauczenie się pracy z DTO.

Każde wejście jest bardzo doceniane.

+0

Należy pamiętać, że być może tworzysz anemiczny model domeny. Obiekty domenowe nie wydają się ujawniać żadnego zachowania - to tylko publiczne przyciąganie i ustawianie (co jest niebezpieczne). – hoetz

+0

Zachowałem to proste dla przykładu. – Thomas

Odpowiedz

8

DTO nie stanowią spłaszczonej reprezentacji danych, mimo że mogą.

To ich piękno - możesz je ułożyć tak, jak potrzebujesz, w przeciwieństwie do definicji bazy danych. Są także sposobem na oddzielenie danych od zachowania.

W ogóle nie wstawiłbym odniesienia do obiektu Domain w DTO. (Masz to w konstruktorze) Użyj fabryki do zbudowania DTO, aby Twoi klienci potrzebowali tylko odniesienia do DTO, a nie obiektów Domeny.

Song mySong; 
SongDTO = DTOFactory.GetSong(mySong); 

Jeśli Twoi klienci muszą odwoływać się do obiektów Domeny, mogą równie dobrze z nich korzystać!

+0

Dzięki. Innymi słowy, zagnieżdżanie DTO jest akceptowalnym podejściem? – Thomas

+2

Absolutnie - po prostu nie mieszaj i dopasowuj DTO z obiektami domeny! – BonyT

0

To, co zrobiłeś, jest poprawne. Myślę, że są one zasadniczo spłaszczoną reprezentacją, gdy przekazujesz dane do/z warstwy danych aplikacji.