嵌套 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 在视图上显示 streets 在 city 中,不是吗?)。 =14=]
我的下一个想法是完全放弃 streets collection,而是提供一个 API 端点来获取 streets[= 城市的 41=]:
api/cities/3737/streets
这样我可以获取 街道 的完整列表,但是 returned 数据不包含街道所属位置的任何信息。如果我的客户现在想要显示 streets 和 city,他必须进行 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 万条街道有点过分了 ;)
鉴于我有一个表示 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 在视图上显示 streets 在 city 中,不是吗?)。 =14=]
我的下一个想法是完全放弃 streets collection,而是提供一个 API 端点来获取 streets[= 城市的 41=]:
api/cities/3737/streets
这样我可以获取 街道 的完整列表,但是 returned 数据不包含街道所属位置的任何信息。如果我的客户现在想要显示 streets 和 city,他必须进行 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 万条街道有点过分了 ;)