Могут ли 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? Насколько я понимаю, DTOs-это сглаженное представление данных, и этот подход не сглажен. С другой рука, я не вижу, как еще это сделать, так как каждый матч специфичен для каждой песни.
Я знаю, что я мог бы сделать это проще для себя и выбросить DTO и передать модель домена непосредственно контроллеру и назвать его днем. Но я не хочу этого делать, так как вся цель состоит в том, чтобы научиться работать с DTO.
любой вход очень ценится.
2 ответов
DTO не являются сплющенным представлением данных, хотя они могут быть.
в этом их красота - вы можете структурировать их так, как вам нужно, в отличие от того, как база данных определяет вещи. Кроме того, они являются средством отделения данных от поведения.
Я бы вообще не помещал ссылку на объект домена в DTO. (У вас есть это в конструкторе) используйте фабрику для создания DTO, поэтому вашим клиентам нужно ссылаться только на DTO, а не на домен объекты.
Song mySong;
SongDTO = DTOFactory.GetSong(mySong);
Если вашим клиентам нужно ссылаться на объекты домена, они могут также использовать их!
то, что вы сделали правильный. Я думаю, что они, по существу, плоское представление, когда вы передаете данные в/из уровня данных приложения.