将数据从服务器传递给客户端时,我应该使用DTO吗?

时间:2014-03-03 17:19:28

标签: c# json dto

我觉得我已经过去使用DTO过度复杂了我的设计,但我正在寻找第二意见。

我的结构是:

  • 用户< - 一对多 - >播放列表< - 一对多 - > PlaylistItem< - One-to-One - >视频

因此,PlaylistItem域对象如下所示:

public class PlaylistItem
{
    public virtual Guid Id { get; set; }
    public virtual Playlist Playlist { get; set; }
    public virtual int Sequence { get; set; }
    public virtual string Title { get; set; }
    public virtual Video Video { get; set; }

    //  Not written to the database. Used for client to tell who is who after a save.
    public virtual string Cid { get; set; }
}

和PlaylistItem DTO看起来像:

[DataContract]
public class PlaylistItemDto
{
    [DataMember(Name = "playlistId")]
    public Guid PlaylistId { get; set; }

    [DataMember(Name = "id")]
    public Guid Id { get; set; }

    [DataMember(Name = "sequence")]
    public int Sequence { get; set; }

    [DataMember(Name = "title")]
    public string Title { get; set; }

    [DataMember(Name = "video")]
    public VideoDto Video { get; set; }

    [DataMember(Name = "cid")]
    public string Cid { get; set; }
}

唯一的变化是我通过用PlaylistId替换播放列表引用来打破循环引用结构。

C#.NET MVC中的默认JSON序列化程序无法处理循环结构。我已经更新到使用能够处理循环结构的JSON.NET序列化器。我现在正在重新评估为什么我甚至需要我的DTO。

在这里我应该注意/考虑DTO是否有任何好处?将JSON化循环引用并通过网络发送是不好的做法吗?

2 个答案:

答案 0 :(得分:2)

作为分层格式的JSON在以分层方式表示数据时将发挥最佳作用。 JSON不是一个节点图,因此我认为尝试序列化类图数据将会很困难。我认为您将对象(Playlist)转换为“引用”(PlaylistId)形式的解决方案是正确的。接收和处理此JSON的代码可以在必要时重新构建循环引用,因为您已准备好“外键”(PlaylistId)。

大多数时候,我宁愿有一个额外的DTO而不是没有。 DTO将您与变更隔离开来 - 在这种情况下,将您的 API 与变更隔离开来。 PlaylistId不太可能在将来更改其架构,但实际的Playlist可能会更改。

答案 1 :(得分:2)

  

在这里我应该注意/考虑DTO是否有任何好处?

设计。这是一个公共API,你想确保它是黑貂,而内部对象是/可以改变而不需要大量的审查。如果这是一个“服务器外”样式的界面,并且您不希望每次进行微小更改时都强制进行API更新(客户端更新),那么数据类型的更改就会出现问题。

因此,单独定义API级别定义对象(DTO)有助于这部分不更改公共接口。