Могут ли DTO иметь вложенные 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; }
}

Моя служба имеет следующий код:

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

Моя служба получает список воспроизведения и песни из базы данных, а затем для каждой песни в списке воспроизведения он запускает запрос на получить дополнительные совпадения из базы данных (с помощью полнотекстового поиска SQL Server), относящиеся к этой песне.

Затем данные преобразуются в DTO, добавляются к объекту результата и передаются обратно в контроллер. Код выглядит следующим образом:

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

Проблема:

Объект PlaylistResult до сих пор работал отлично, но недавнее введение совпадений немного усложнило ситуацию. Похоже, у меня нет другого выбора, кроме как изменить мой SongDTO, чтобы учесть совпадения, и он будет выглядеть следующим образом:

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

Но не нарушает ли это цели DTO? Насколько я понимаю, DTO представляют собой плоское представление данных, и этот подход не является плоским. С другой стороны, я не знаю, как еще это сделать, поскольку каждое совпадение индивидуально для каждой песни.

Я знаю, что могу упростить себе эту задачу и выбросить DTO и передать модель предметной области в контроллер напрямую и на этом все закончится. Но я не хочу этого делать, поскольку вся цель - научиться работать с DTO.

Любой ввод приветствуется.

8
задан Thomas 29 June 2011 в 16:35
поделиться