我有术语问题。与Fowler相比,DTO是“在进程之间传送数据以减少方法调用次数的对象”。 (http://martinfowler.com/eaaCatalog/dataTransferObject.html)。据我了解,减少方法调用的唯一方法是将它们统一起来。因此DTO是复合对象,包含一些实体。
例如,我们有两个简单的实体CoinInfo和ProductInfo:
public class CoinInfo
{
public int CoinId { get; set; }
public int Denomination { get; set; }
public int Quantity { get; set; }
}
public class ProductInfo
{
public int ProductId { get; set; }
public ProductTypes ProductType { get; set; }
public int Price { get; set; }
public int Count { get; set; }
}
我们还拥有将CoinInfo和ProductInfo结合在一起的复杂对象SomeDto。
public class SomeComplex
{
public List<CoinInfo> UserWallet { get; set; }
public List<ProductInfo> Products { get; set;}
}
那么,ProductInfo和CoinInfo也是“ DTO”还是“实体”?
最佳答案
当您跨越类,组件或应用程序边界时,数据传输对象就会发挥作用。您使用DTO减少类,组件或应用程序之间的耦合。
例如,当构建要由客户端使用的服务时,您可能需要引入三个组件:
服务:包含业务逻辑,也许还包含一些服务托管样板(尽管您通常希望在其自己的项目中最后一点)。
客户端库:应用程序可以用来调用服务中的方法
数据传输对象:服务和客户端均引用这些对象。
现在,希望与该服务进行通信的客户端应用程序只需引用客户端库和DTO库。您的服务使用什么其他类型来发挥其魔力,对客户端一点都不感兴趣,并且应该保持隐藏。
现在,DTO的要点是您可以使用它们来对API进行建模。您可以决定从服务中获得什么,以及这些数据的外观。您可以选择组成,将较小的DTO聚合为较大的DTO,如图所示。
您要记住的是不要通过DTO公开服务内部信息。您使用的是“实体”一词,这使我认为您正在尝试公开例如DTO中聚合的实体框架模型。您不应该这样做。这样做是在创建“泄漏抽象”,这使得更改数据库(添加或删除列,替换ORM等)和更改服务返回的信息(添加或删除属性)变得更加困难。 ..)。除此之外,使用Entity Framework模型作为DTO会带来批量分配,延迟加载和循环引用等问题,所有这些都需要解决方法。
您可以使用属性来解决这些潜在问题,以使您的ORM或服务序列化程序忽略那些无关的属性,但是这些仍然是解决方法。如果您确实需要公开看起来很像您的数据模型的DTO,请引入映射(例如,使用AutoMapper):
Service.Data:包含“实体”。
服务:将“实体”映射到DTO,并返回/接受后者。
客户端库:仍然只看到并且需要引用DTO。
在这种情况下,服务的数据层和从服务返回的模型是分离的。
如果所有这些都不是您关心的,而仅仅是命名法:是的,您显示的所有三个类都是DTO。