8

我有以下域模型: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合作。

任何輸入,非常感謝。

+0

請注意,您可能正在創建貧血區域模型。你是域對象似乎沒有暴露任何行爲 - 這只是公共的getter和setter(這是危險的)。 – hoetz

+0

爲了舉例,我保持簡單。 – Thomas

回答

8

DTO's不是數據的扁平表示,儘管它們可以是。

這就是它們的美妙之處 - 您可以根據需要構造它們,而不是數據庫如何定義事物。他們也是從行爲中分離數據的手段。

我不會在DTO中引用Domain對象。 (你在構造函數中使用它)使用工廠來構建DTO,所以你的客戶只需要引用DTO的而不是Domain對象。

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

如果您的客戶需要引用Domain對象,那麼他們也可以使用它們!

+0

謝謝。換句話說,嵌套DTO是一種可接受的方法? – Thomas

+2

絕對 - 只要不混合和匹配DTO的域對象! – BonyT

0

你所做的是正確的。我認爲,當你將數據傳遞到應用程序的數據層時,它們本質上是扁平的。