谈谈我对实体的认识:DTO,DMO,DPO

简介:

今天和大家谈的是我对于实体的一些认识,难免有偏颇之初,还请各位指出。

 

大家都看到标题中的三个英文缩写了:DTO,DMO,DPO。DTO大家应该还是熟悉的,Data Transfer Ojbect(数据传输对象)。研究过DDD(Domain Driven Design领域驱动设计)的人应该了解过DTO。是用来传输数据的对象,应为领域对象虽然有数据(属性),但是领域对象上面还带有操作,在某些场合不适合进行传输,因为有些时候传输还需要序列化,而且也不是所有的领域对象属性都可以暴露给调用端的,而且有些属性可能要合并,可能要分解,之后才有利于调用端的使用,加上其他一些的业务原因,于是就有了专门用来传输数据的DTO,只有属性,没有操作,必要的时候加上序列化标记,实现远程调用。

 

DMO和DPO是我自己创造的名词,在后面再解释给大家听。

 

刚开始看到别人用来表达数据对象的类的时候,都是只有属性,没有操作,而且大都是和数据库表一一对应的。可以单独建立一个项目,名字叫做Project.Entity。在独立的一个项目中保存所有用到的实体,其他的项目添加对Project.Entity项目的引用。

entity1

 

就拿User举个例子吧。

public  class User {  public Guid UserID {  getset; }  public  string Username {  getset; } }


 

也有人喜欢在实体类添加后缀,方便标识,因为有可能领域对象也叫做User,但是觉得都叫做User又有点别扭,不好区分。就像分层的话,可能会有UserBll,UserDal之类的类产生。(在这里不讨论这些类是否合适,只是说明这种现象,但是如果大家有这方面的好思路,也可以分享一下)

 

然后不管是添加还是修改,还是查询显示,都是用这个User实体。这个在做ASP.NET或者WinForm的时候还可以。反正客户端和服务端都可以引用这个类库,不影响开发。

 

有一点,我个人比较喜欢将一些查询条件作为一个实体的属性。这样查询方法就不需要很多参数了,只有一个实体作为参数就可以了。而且在后面如果条件有变化,只要在实体添加属性,方法的内部添加或者删除参数的处理就可以了。至少调用端不用做任何修改。如果每个添加都作为一个参数的话,增加或者删除参数,服务端修改方法,调用端就需要修改调用的地方。也能减少一些开发工作吧,而且在界面的查询条件很多的时候,不至于查询方法的参数列表也很长。

例如用户查询,我就会建立一个UserFind实体。下面的例子中说明界面有两个条件,一个是用户姓名,一个是注册时间。

public  class UserFind {  public  string Username {  getset; }  public DateTime RegDate {  getset; } }

 

问题1

产生的问题就是添加的时候肯定是每个属性都要添加到数据库,修改的时候,有些属性不用或者是不能修改,允许部分的修改。还有就是显示的时候,可能还需要其他的属性,例如User实体下面可能会有一些集合属性,例如用户全部地址,邮件个数,是否有新邮件,是否有新订单之类的需求,就要在User实体添加其他属性。但是这些属性在添加和修改的时候都用不到。如果这几种情况还是共享一个实体的话,容易引起误用。而且增加沟通,需要告诉做添加功能的人,你只要添加属性1,2,3就可以了。告诉做显示的人,你需要每个属性都赋值。告诉做修改的人,属性2,3,4,5是可以修改的。

 

还有那个查询实体,例如查询订单吧。用户查询订单,只能查询自己的订单。

public  class OrderFind {  public  string OrderSeqNo {  getset; }  public DateTime PlaceDate {  getset; } }


根据订单编号和下单时间查询。

可是后台查询用户订单的时候,可能会需要用户的信息,例如查询姓名为“张三”的订单。好吧,修改这个查询实体。

public  class OrderFind {  public  string OrderSeqNo {  getset; }  public DateTime PlaceDate {  getset; }  public  string Username {  getset; } }


 

 

 

问题2

同样,这就需要在开发用户查询订单的时候忽略Username属性,在开发后台查询订单的时候加上Username属性。

是不是这两个功能也应该区分一下呢?

于是我就有了下面的总结。

1、实体的专用性

1) 尽量的保持实体的专用性,也就是一个功能的方法,虽然和两外一个方法的返回结果类似,可能只需要添加一两个属性,这样的情况,重新建立实体,方便后面可能对这两个方法返回内容的修改不至于相互影响。

2) 尽量保持一个实体中的每一个属性,每一个被赋值的属性,将来都会用到,否则减少实体的属性,或者新建一个实体,使用正好合适的属性个数。

3) 分离添加和显示用的实体,因为添加可能不是每个字段都需要赋值,或者一些值是默认值。

4) 分离不同类型的用户使用的实体,尽管是相同的功能。可以在类名添加ForPlanter之类的后缀来解决。因为不同用户关注的点不同,关注的属性肯定不相同。而且修改也不影响其他类型用户的使用。

最近的一个项目是WCF+Silverlight。一个类库项目不行了,需要添加两个类库项目,因为Silverlight不能添加普通类库引用,Silverlight有自己的类库项目模板。

当然了,实体的代码还是可以共享的,但是类库必须是两个。

 

在简单学习了DDD之后,发现里面的一个概念叫做DTO,数据传输对象。觉得其他和我的Project.Entity项目比较像,反正功能都是用来承载数据,不带有任何操作。甚至连数据验证都没有,数据验证可以通过attribute,集合独立的模块来完成。

 

问题2已经有了解决方案,就是保持实体的专用,减少混用。

 

可是问题1呢?

后来我们想减少代码的开发量,尤其是在增、删、改、查的数据库操作方面,想要引进一些工具类库,来帮助我们完成数据库的操作,使得我们可以专注于业务方面的开发。

这方面的类库有很多,例如:NHibernate,还有微软的Entity Framework等。引入这些时候我发现问题1变得更加突出了。要不然就会有大量的冗余字段被读取,甚至被网络传输(WCF+Silverlight的数据需要经过网络,SOAP消息的形式传输到客户端)。

 

于是DTO,DPO,DMP就产生了。

1、传输实体,经过客户端传输给wcf。在服务端可能需要组合产生新的数据库持久化实体(区分添加用实体和更新用实体),这些实体经过ORM将数据持久化到数据库。

2、从数据库查询的数据,经过ORM映射产生的实体,然后经过处理,产生传输实体,传输给客户端。

3、数据传输实体dto,数据库持久化实体dpo,数据库映射实体dmo

Technorati 标签:  , , ,



本文转自 virusswb 51CTO博客,原文链接:http://blog.51cto.com/virusswb/432831,如需转载请自行联系原作者
目录
相关文章
|
达摩院 Linux API
阿里达摩院MindOpt求解器V1.1新增C#接口
阿里达摩院MindOpt求解器发布最新版本V1.1,增加了C#相关API和文档。优化求解器产品是求解优化问题的专业计算软件,可广泛各个行业。阿里达摩院从2019年投入自研MindOpt优化求解器,截止目前经历27个版本的迭代,取得了多项国内和国际第一的成绩。就在上个月,2023年12月,在工信部产业发展促进中心等单位主办的首届能源电子产业创新大赛上,MindOpt获得电力用国产求解器第一名。本文将为C#开发者讲述如何下载安装MindOpt和C#案例源代码。
830 3
阿里达摩院MindOpt求解器V1.1新增C#接口
|
人工智能 算法 决策智能
OR-tools求解器使用介绍(一)
OR-tools求解器使用介绍(一)
2088 0
|
10月前
|
人工智能 IDE 编译器
如何用给各种IDE配置R语言环境
R语言虽无Python式虚拟环境,但通过Conda管理或多项目隔离方案(如自定义.libPaths或使用renv工具),可实现包依赖独立、版本锁定与环境复现,支持跨平台迁移与协作,真正做到“一次配置,永久可用”。推荐renv+RStudio组合,高效管理项目环境。
|
存储 SQL 分布式计算
Apache Iceberg数据湖基础
Apache Iceberg 是新一代数据湖表格式,旨在解决传统数据湖(如 Hive)在事务性、并发控制和元数据管理上的不足。它支持 Spark、Flink、Trino 等多种计算引擎,提供 ACID 事务、模式演化、分区演化等核心特性,具备良好的云存储兼容性和高性能查询能力,适用于大规模结构化数据分析场景。
2226 0
|
敏捷开发 监控 数据可视化
敏捷开发的6大方法与模型,帮助你快速适应项目需求变化
3分钟了解6种常见的敏捷开发方法,包括Scrum,看板Kanban,极限编程(XP),DSDM、特征驱动开发和水晶法等方法。
3123 5
敏捷开发的6大方法与模型,帮助你快速适应项目需求变化
|
消息中间件 监控 数据可视化
基于.NET开源、功能强大且灵活的工作流引擎框架
基于.NET开源、功能强大且灵活的工作流引擎框架
1064 3
|
安全 开发工具 git
git合并错了,我想回退到之前的版本
git合并错了,我想回退到之前的版本
|
IDE 网络安全 开发工具
IDE之vscode:连接远程服务器代码(亲测OK),与pycharm链接服务器做对比(亲自使用过了),打开文件夹后切换文件夹。
本文介绍了如何使用VS Code通过Remote-SSH插件连接远程服务器进行代码开发,并与PyCharm进行了对比。作者认为VS Code在连接和配置多个服务器时更为简单,推荐使用VS Code。文章详细说明了VS Code的安装、远程插件安装、SSH配置文件编写、服务器连接以及如何在连接后切换文件夹。此外,还提供了使用密钥进行免密登录的方法和解决权限问题的步骤。
12648 0
IDE之vscode:连接远程服务器代码(亲测OK),与pycharm链接服务器做对比(亲自使用过了),打开文件夹后切换文件夹。
|
机器学习/深度学习 搜索推荐 算法
深度学习在推荐系统中的应用:技术解析与实践
【7月更文挑战第6天】深度学习在推荐系统中的应用为推荐算法的发展带来了新的机遇和挑战。通过深入理解深度学习的技术原理和应用场景,并结合具体的实践案例,我们可以更好地构建高效、准确的推荐系统,为用户提供更加个性化的推荐服务。
1056 5