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 gets a playlist and songs from the database and then for each song in the playlist it fires a query to get additional matches from the database (using SQL Server full text search) specific to that song.
The data is then converted into DTO's, added to a result object and passed back to the controller. The code looks like:
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; }
}
The problem:
The PlaylistResult object has worked great so far but the recent introduction of matches has made things a bit more complicated. It looks like I have no other choice than to modify my SongDTO to take into account 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 this violate the purpose of DTO's? It is my understanding that DTOs are a flattened representation of data and this approach is not flattened. On the other hand, I don't see how else to do this since each match is specific to each song.
I am aware that I could make this easier on myself and throw out the DTO's and pass the domain model to the controller directly and call it a day. But I don't want to do that since the whole purpose is to learn how to work with DTO's.
Any input is greatly appreciated.
DTO's are not a flattened representation of data although they can be.
That's the beauty of them - you can structure them as you need to, as opposed to how the database defines things. Also they are a means of separating out data from behaviour.
I wouldn't put a reference to the Domain object within the DTO at all. (You have it in the constructor) Use a factory to build the DTO's so your clients only need reference the DTO's and not the Domain objects.
Song mySong;
SongDTO = DTOFactory.GetSong(mySong);
If your clients need to reference the Domain objects, then they may as well use them!
What you have done is correct. I think that they are essentially flattened representation when you are passing data to/from the data layer of your application.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With