嵌套 collections 的 DTO 设计注意事项

DTO design considerations for nested collections

鉴于我有一个表示 city 的模型,其中包含 streets 的 collection。

public class City {
    public int Id { get; set; }
    public string Name { get; set; }
    public IEnumerable<Street> Streets { get; }
}

public class Street {
    public int Id { get; }
    public string Name { get; }
    public IEnumerable<Building> Buildings { get; }
}

如果客户对 所有 个城市 (api/cities/all) 感兴趣,我会 return 他全部 collection,这会导致大量响应,具体取决于数据集的大小。所以我首先想到的是 return 在 街道 collection 内仅 街道 ID。然而,这感觉很尴尬,因为虽然 ids 可能对进一步获取街道有用,但它们对客户没有任何意义(填充 [=24 的列表没有意义) =]ids 在视图上显示 streetscity 中,不是吗?)。 =14=]

我的下一个想法是完全放弃 streets collection,而是提供一个 API 端点来获取 streets[= 城市的 41=]:

api/cities/3737/streets

这样我可以获取 街道 的完整列表,但是 returned 数据不包含街道所属位置的任何信息。如果我的客户现在想要显示 streetscity,他必须进行 2 次 API 调用才能获得他需要的信息。

return 此类数据的常用方法是什么?

我会创建 2 个城市对象,一个只包含基本数据(如 ID 和名称)的城市对象和一个包含所有数据(包括完整街道规划)的 cityDetail 对象。
根据您的情况,您可以对建筑物重复此模式。
然后,您可以 return 列表调用中的城市对象,只有在执行 get by id 时,您才会 return cityDetail 对象。


不好 => 你的 api 有点像 "inconsistent" 因为你通过列表​​获得的城市对象与你通过 get 获得的城市对象不同。您可以创建 2 个资源:city 和 cityDetail,其中 cityDetail 没有 List 函数,city 没有 getByID 函数,但它仍然不如单个资源干净和可预测。

好的 => 性能明智和使用明智这通常是一个完美的匹配。您永远不会显示带有街道的城市列表,因此城市对象就足够了。当您查看单个城市时,您很可能希望显示包括街道在内的所有数据(或至少在该页面上使用此数据),因此 cityDetail 对象也适合此处。
就性能而言,很明显为 getAllMyCities 调用获取 100 万条街道有点过分了 ;)