Can a DTO embed a DTO?

I have the following domain model:

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; } } 

My service has the following code:

 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))); } 

My service receives a playlist and songs from the database, and then for each song in the playlist, it launches a query to get additional matches from the database (using full-text search on SQL Server) specific to this song.

Then the data is converted to DTO, added to the result object, and passed back to the controller. The code looks like this:

 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:

The PlaylistResult object has been working fine so far, but the recent introduction of matches has complicated the situation. It looks like I have no choice but to change my SongDTO to allow for matches and look like this:

 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; } } 

But doesn't that violate the purpose of the DTO? I understand that DTO is a flat representation of the data, and this approach is not flattened. On the other hand, I don’t see how to do this, since each match depends on each song.

I know that I could make it easier for myself and throw away the DTO and pass the domain model directly to the controller and call it day. But I do not want to do this, because the goal is to learn how to work with DTO.

Any input is welcome.

+8
design-patterns asp.net-mvc-3 domain-driven-design ddd-repositories
source share
2 answers

DTOs are not a smooth presentation of data, although they may be.

What is their beauty - you can structure them as you need, in contrast to how the database defines things. They are also a means of data branch behavior.

I would not refer to the Domain object inside the DTO. (You have this in the constructor) Use factory to create a DTO so that your customers only need a DTO reference, not a Domain object.

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

If your clients need to refer to domain objects, then they can also use them!

+8
source share

What you did is right. I think that they are essentially a flattened representation when you pass data to / from the data layer of your application.

0
source share

All Articles