文档目录 本节内容:DTO 必要性领域层的抽象数据隐藏序列化和延迟加载问题DTO 约定和验证示例DTO和实体间自动映射使用特性和扩展方法进行映射辅助接口和类 Data Transfer Objects(DTO)用来在应用层和展现层之间传输数据。展现层使用一个DTO调用一个 ...
文档目录
本节内容:
- DTO 必要性
- DTO 约定和验证
- DTO和实体间自动映射
- 辅助接口和类
Data Transfer Objects(DTO)用来在应用层和展现层之间传输数据。
展现层使用一个DTO调用一个应用服务方法,然后应用服务使用服务对象执行一些特定业务逻辑,并返回一个DTO给展现层。因此,展现层是完全独立于领域层的。在一个理想的分层应用里,展现层不直接使用领域对象(仓储、实体...)。
DTO 必要性
首先为每个应用服务方法创建一个DTO看起来是件乏味且费时的工作,但如果你正确使用它,它能解救你的应用。为什么呢?
领域层的抽象
dto提供一个有效的方法从展现层抽象领域对象,因此,你的层正确分离开,即使你想完全地改变展现层,也可以继续使用已存在的应用和领域层。相反,你可以重写你的领域层、完全改变数据库结构、实体和ORM框架,只要你的应用服务契约(方法签名和DTO)保持不变,展现层也不用做任何修改。
数据隐藏
考虑一下:你有一个User实体,它有Id、Name、EmailAddress和Password属性,如果UserAppService的GetAllusers()方法返回一个List<User>,任何人都可以看到所有用户的密码,即使你没有在屏幕上显示它,也是不安全的。不只是数据安全,还有关于数据的隐藏,应用服务应该只向展现层返回必要的数据,不多也不少。
序列化和延迟加载问题
当你返回一个数据(一个对象)给展现层时,它可能会在某处被序列化,例如:在一个返回Json的MVC方法里,你的对象会被序列化成JSON,然后发送给客户端,在这种情况下,如果返回一个实体给展示层可能会有问题,为什么呢?
在一个真实的应用里,你的实体间可能存在相互引用,User实体可能关联到Roles,所以如果你想序列化User,那么它的Roles也要被序列化,而Role类可能包含一个List<Permission>,Permission类可能又关联到PermissionGroup类等等。你能想到序列化这些对象,可能你就意外的序列化了你整个数据库,而如果你的对象存在循环引用,它就不能被序列化了。
怎么解决呢?把属性标记为NonSerialized(不序列化)?不,你不知道它何时应当被序列化又何时不应当被序列化,可能在这个应用服务里要序列化,而在另一个服务里不要序列化,所以返回一个安全地可序列化的,特殊设计的DTO是一个好的选择。
几乎所有ORM框架都支持延迟加载,它是一个在需要时从数据库加载实体的特性。假设User类有一个指向Role类的引用,当你从数据库获取一个User时,Role属性没有被填充,当你第一次读取Role属性时,它再从数据库中加载。所以你返回这么一个实体给展现层,它将去数据库获取额外的实体。如果一个序列化工具读取这个实体,它递归读取所有属性,可能又会序列化你整个数据库(如果实体间存在适当的关系)。
我们可以说出在展现层使用实体的更多问题,最好的做法是在应用层里不引用包含领域(业务)层的程序集。
DTO 约定和验证
ABP强支持DTO,它提供了一些约定类和接口,并建议了一些命名和使用约定,当你如本节描述的这样去写代码,ABP会自动完成一些任务。
示例
让我们看一个完整的示例,假设我们想开发一个通过name搜索people并返回一个people列表的应用服务,这样,我们应该有一个Person实体,如:
public class Person : Entity{ public virtual get='_blank'>string Name { get; set; } public virtual string EmailAddress { get; set; } public virtual string Password { get; set; }}
原标题:ABP框架 数据传输对象
关键词:
*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们:
admin#shaoqun.com
(#换成@)。