全胖还是瘦 DTO objects?

Full fat or skinny DTO objects?

我要return Full-Fat Dtos;即使用基本的 parent 实体信息,它的 ID 和名称,以及 child 实体的集合转换为 child dto 的集合;或去掉所有东西,只有 parent 个实体的 return 个 ID?

瘦的选择会导致大量调用 web-api 来填充缺失的细节,但是 full-fat dto 将是一个相当重的 object 如果一个实体有许多 child、grand-child 等关系。

是否有 semi-skimmed 选项可以在特定级别停止 dto 序列化?

要添加一些额外的上下文:我们正在包装第 3 方 api 供内部使用。第 3 方正在使用 "skinny" 方法处理 return ~18,000 个实体,大约 18mb。

要使其不仅仅是一个 ID 集合,我们至少需要添加一些上下文。 Id 和 Name 实体很简单,可以包含但是相关字段可能具有 child 关系,由于底层数据库设计导致有趣的循环关系,事情变得有趣...

我一直倾向于 "full-fat" DTO 方法,正如您所说的那样。性能是一项功能,没有比增加一堆不必要的网络延迟更好的降低性能的方法了。

我会说,除非你正在处理一个资源严重紧张的机器,否则不要全力以赴,以减少往返服务器的往返次数。

您没有提供太多信息,但我想您在这里得到了数据库表的支持?如果是这样,我更愿意将 "entities" 公开为单个数据库记录的纯粹表示(显然省略了敏感字段)。并创建一个 RESTful API 来公开和导航它。

EDIT: To elaborate with some code on what I mean by "full-fat" (note: certain superfluous details are omitted to reduce the verbosity).

示例 SQL 设置:

create table dbo.User (
    Id int identity primary key,
    Name nvarchar(50)
);

create table dbo.Post (
    Id int identity primary key,
    UserId int not null foreign key references dbo.User(Id),
    Title nvarchar(50),
    Body nvarchar(max)
);

示例 CLR 对象:

public sealed class User 
{
    public int Id { get; set; } 
    public string Name { get; set; }

    public IEnumerable<Post> Posts { get; set; }
}

public sealed class Post 
{
    public int Id { get; set; } 
    public int UserId { get; set; } 
    public string Title { get; set; }   
    public string Body { get; set; }

    public User User { get; set; }
}

鉴于上述设置,有关如何以 REST 方式公开对象的示例如下:

/api/users            /*users collection*/
/api/users/1          /*user resource*/
/api/users/1/posts    /*user resource with posts sub-collection*/

/api/posts            /*posts collection*/
/api/posts/1?user=1|0 /*post resource with/without User*/

选择完全取决于您应用解决方案的环境。

我通常把两者混在一起。如果我有 'master-detail' 类型的视图,例如网上商店,并且我必须在用户只能看到产品名称和价格的列表中显示产品,那么我选择 'skinny' 版本.然后,用户点击商品可以看到详情页,我发的是'full-fat'版本。

但是如果每个产品都有一个类别,我可能只会在 'detail' 产品 dto 中发送类别 ID 和类别名称。然后,当用户单击某个类别以查看类别详细信息和其他产品时,我会发送其余部分。

答案是 "Do you need "Full-Fat" Dto?"

Return 只提供您需要的数据。 例如 Customer-Orders 结构

  • 对于仅使用 customer.Idcustomer.Name 的方法,您只能 return { Id: 1, Name: "One" }
  • 对于需要更多客户信息的方法,您将return更多信息
    { Id: 1, Name: "One", Street: "Street 12", City: "City" }
  • 对于需要更复杂数据的方法,您将创建 api return 更复杂的数据

不要尝试从一开始就通用,开发应用程序所需的具体 API 方法,然后您可以看到全局并重构方法以使其更通用,并进行不同的权衡