15

我有以下域模型:

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。

非常感谢任何输入。

4

2 回答 2

13

DTO 不是数据的扁平化表示,尽管它们可以。

这就是它们的美妙之处——您可以根据需要构建它们,而不是数据库如何定义事物。它们也是一种将数据与行为分离的方法。

我根本不会在 DTO 中引用 Domain 对象。(您在构造函数中有它)使用工厂来构建 DTO,因此您的客户只需要引用 DTO 而不是域对象。

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

如果您的客户需要引用域对象,那么他们也可以使用它们!

于 2011-06-29T16:44:07.343 回答
1

你所做的是正确的。我认为当您向/从应用程序的数据层传递数据时,它们本质上是扁平化的表示。

于 2011-06-30T09:07:27.123 回答