C# 普通旧 CLR 对象与数据传输对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/725348/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 22:38:46  来源:igfitidea点击:

Plain Old CLR Object vs Data Transfer Object

c#.netpocodto

提问by Patrick Peters

POCO = Plain Old CLR (or better: Class) Object

POCO = 普通的旧 CLR(或更好:类)对象

DTO = Data Transfer Object

DTO = 数据传输对象

In this postthere is a difference, but frankly most of the blogs I read describe POCO in the way DTO is defined: DTOs are simple data containers used for moving data between the layers of an application.

在这篇文章中有一个不同之处,但坦率地说,我读过的大多数博客都以 DTO 的定义方式描述了 POCO:DTO 是用于在应用程序层之间移动数据的简单数据容器。

Are POCO and DTO the same thing?

POCO 和 DTO 是一回事吗?

采纳答案by Michael Meadows

A POCO follows the rules of OOP. It should (but doesn't have to) have state andbehavior. POCO comes from POJO, coined by Martin Fowler [anecdote here]. He used the term POJO as a way to make it more sexy to reject the framework heavy EJB implementations. POCO should be used in the same context in .Net. Don't let frameworks dictate your object's design.

POCO 遵循 OOP 的规则。它应该(但不是必须)有状态行为。POCO 来自 POJO,由 Martin Fowler 创造 [这里的轶事]。他使用术语 POJO 作为一种方式,使拒绝框架繁重的 EJB 实现变得更加性感。POCO 应该在 .Net 中的相同上下文中使用。不要让框架决定你的对象的设计。

A DTO's only purpose is to transfer state, and should have no behavior. See Martin Fowler's explanation of a DTOfor an example of the use of this pattern.

DTO 的唯一目的是转移状态,不应有任何行为。有关使用此模式的示例,请参阅 Martin Fowler对 DTO解释

Here's the difference: POCO describes an approach to programming(good old fashioned object oriented programming), where DTO is a patternthat is used to "transfer data" using objects.

区别在于:POCO 描述了一种编程方法(良好的老式面向对象编程),其中DTO 是一种用于使用对象“传输数据”的模式

While you can treat POCOs like DTOs, you run the risk of creating an anemic domain modelif you do so. Additionally, there's a mismatch in structure, since DTOs should be designed to transfer data, not to represent the true structure of the business domain. The result of this is that DTOs tend to be more flat than your actual domain.

虽然您可以像对待 DTO 一样对待 POCO,但如果这样做,您将面临创建贫血域模型的风险。此外,在结构上存在不匹配,因为 DTO 应该被设计为传输数据,而不是代表业务领域的真实结构。这样做的结果是 DTO 往往比您的实际域更扁平。

In a domain of any reasonable complexity, you're almost always better off creating separate domain POCOs and translating them to DTOs. DDD (domain driven design) defines the anti-corruption layer(another link here, but best thing to do is buy the book), which is a good structure that makes the segregation clear.

在具有任何合理复杂性的域中,您几乎总是最好创建单独的域 POCO 并将它们转换为 DTO。DDD(领域驱动设计)定义了反腐败层这里的另一个链接,但最好的办法是买本书),这是一个很好的结构,使隔离清晰。

回答by Davy Landman

I think a DTO can be a POCO. DTO is more about the usage of the object while POCO is more of the style of the object (decoupled from architectural concepts).

我认为 DTO 可以是 POCO。DTO更多是关于对象的使用,而POCO更多的是对象的风格(与架构概念解耦)。

One example where a POCO is something different than DTO is when you're talking about POCO's inside your domain model/business logic model, which is a nice OO representation of your problem domain. You could use the POCO's throughout the whole application, but this could have some undesirable side effect such a knowledge leaks. DTO's are for instance used from the Service Layer which the UI communicates with, the DTO's are flat representation of the data, and are only used for providing the UI with data, and communicating changes back to the service layer. The service layer is in charge of mapping the DTO's both ways to the POCO domain objects.

POCO 与 DTO 不同的一个例子是,当您谈论域模型/业务逻辑模型中的 POCO 时,这是您问题域的一种很好的 OO 表示。您可以在整个应用程序中使用 POCO,但这可能会产生一些不良副作用,例如知识泄漏。例如,DTO 用于 UI 与之通信的服务层,DTO 是数据的平面表示,仅用于向 UI 提供数据,并将更改传达回服务层。服务层负责将 DTO 的双向映射到 POCO 域对象。

UpdateMartin Fowler saidthat this approach is a heavy road to take, and should only be taken if there is a significant mismatch between the domain layer and the user interface.

更新Martin Fowler,这种方法是一条艰巨的道路,只有在域层和用户界面之间存在严重不匹配的情况下才应该采用。

回答by John Saunders

A primary use case for a DTO is in returning data from a web service. In this instance, POCO and DTO are equivalent. Any behavior in the POCO would be removed when it is returned from a web service, so it doesn't really matter whether or not it has behavior.

DTO 的主要用例是从 Web 服务返回数据。在这种情况下,POCO 和 DTO 是等效的。当从 Web 服务返回时,POCO 中的任何行为都将被删除,因此它是否具有行为并不重要。

回答by benmmurphy

here is the general rule: DTO==evil and indicator of over-engineered software. POCO==good. 'enterprise' patterns have destroyed the brains of a lot of people in the Java EE world. please don't repeat the mistake in .NET land.

这是一般规则:DTO==evil 和过度设计软件的指标。POCO==好。“企业”模式已经摧毁了 Java EE 世界中很多人的大脑。请不要在 .NET 领域重蹈覆辙。

回答by benmmurphy

It's probably redundant for me to contribute since I already stated my position in my blog article, but the final paragraph of that article kind of sums things up:

因为我已经在我的博客文章中陈述了我的立场,所以我可能会做出贡献,但那篇文章的最后一段总结了一些事情:

So, in conclusion, learn to love the POCO, and make sure you don't spread any misinformation about it being the same thing as a DTO. DTOs are simple data containers used for moving data between the layers of an application. POCOs are full fledged business objects with the one requirement that they are Persistence Ignorant (no get or save methods). Lastly, if you haven't checked out Jimmy Nilsson's book yet, pick it up from your local university stacks. It has examples in C# and it's a great read.

因此,总而言之,要学会热爱 POCO,并确保您不会传播任何关于它与 DTO 相同的错误信息。DTO 是简单的数据容器,用于在应用程序的层之间移动数据。POCO 是成熟的业务对象,其一个要求是它们是 Persistence Ignorant(无 get 或 save 方法)。最后,如果您还没有查看 Jimmy Nilsson 的书,请从您当地的大学书库中挑选。它有 C# 中的示例,非常适合阅读。

BTW, Patrick I read the POCO as a Lifestyle article, and I completely agree, that is a fantastic article. It's actually a section from the Jimmy Nilsson book that I recommended. I had no idea that it was available online. His book really is the best source of information I've found on POCO / DTO / Repository / and other DDD development practices.

顺便说一句,帕特里克我将 POCO 视为一篇生活方式文章,我完全同意,这是一篇很棒的文章。它实际上是我推荐的 Jimmy Nilsson 书中的一个部分。我不知道它可以在线获得。他的书确实是我在 POCO / DTO / Repository / 和其他 DDD 开发实践中找到的最佳信息来源。

回答by Neil

POCO is simply an object that does not take a dependency on an external framework. It is PLAIN.

POCO 只是一个不依赖于外部框架的对象。这是平原。

Whether a POCO has behaviour or not it's immaterial.

POCO 是否具有行为并不重要。

A DTO may be POCO as may a domain object (which would typically be rich in behaviour).

DTO 可能是 POCO,域对象也可能是 POCO(通常具有丰富的行为)。

Typically DTOs are more likely to take dependencies on external frameworks (eg. attributes) for serialisation purposes as typically they exit at the boundary of a system.

通常,DTO 更有可能依赖外部框架(例如属性)以进行序列化,因为它们通常在系统边界处退出。

In typical Onion style architectures (often used within a broadly DDD approach) the domain layer is placed at the centre and so its objects should not, at this point, have dependencies outside of that layer.

在典型的洋葱式架构(通常用于广泛的 DDD 方法中)中,域层位于中心,因此此时它的对象不应在该层之外具有依赖关系。

回答by PositiveGuy

Don't even call them DTOs. They're called Models....Period. Models never have behavior. I don't know who came up with this dumb term DTO but it must be a .NET thing is all I can figure. Think of view models in MVC, same dam** thing, models are used to transfer state between layers server side or over the wire period, they are all models. Properties with data. These are models you pass ove the wire. Models, Models Models. That's it.

甚至不要称它们为 DTO。他们被称为模型......时期。模型永远不会有行为。我不知道是谁提出了这个愚蠢的术语 DTO,但它必须是 .NET 的东西,这是我所能想到的。想想MVC中的视图模型,同一个大坝**的东西,模型用于在服务器端或在线期间在层之间传输状态,它们都是模型。带有数据的属性。这些是您通过电线传递的模型。模型,模型模型。就是这样。

I wish the stupid term DTO would go away from our vocabulary.

我希望愚蠢的术语 DTO 会从我们的词汇表中消失。

回答by Vladimir

I wrote an article for that topic: DTO vs Value Object vs POCO.

我为该主题写了一篇文章:DTO vs Value Object vs POCO

In short:

简而言之:

  • DTO != Value Object
  • DTO ? POCO
  • Value Object ? POCO
  • DTO != 值对象
  • DTO ? POCO
  • 值对象 ? POCO

回答by Herman Van Der Blom

DTO classes are used to serialize/deserialize data from different sources. When you want to deserialize a object from a source, does not matter what external source it is: service, file, database etc. you may be only want to use some part of that but you want an easy way to deserialize that data to an object. after that you copy that data to the XModel you want to use. A serializer is a beautiful technology to load DTO objects. Why? you only need one function to load (deserialize) the object.

DTO 类用于序列化/反序列化来自不同来源的数据。当您想从源反序列化一个对象时,它是什么外部源并不重要:服务、文件、数据库等。您可能只想使用其中的一部分,但您想要一种简单的方法将该数据反序列化为目的。之后,将该数据复制到要使用的 XModel。序列化器是一种加载 DTO 对象的漂亮技术。为什么?您只需要一个函数来加载(反序列化)对象。

回答by Sinaesthetic

TL;DR:

特尔;博士:

A DTO describes the pattern of state transfer. A POCO doesn't describe anything. It's another way of saying "object" in OOP. It comes from POJO (Java), coined by Martin Fowler who literally just describes it as a fancier name for 'object' because 'object' isn't very sexy.

DTO 描述了状态转移的模式。POCO 不描述任何内容。这是在 OOP 中说“对象”的另一种方式。它来自 POJO(Java),由 Martin Fowler 创造,他实际上只是将它描述为“对象”的一个更漂亮的名称,因为“对象”不是很性感。

A DTO is an object pattern used to transfer state between layers of concern. They can have behavior (i.e. can technically be a poco) so long as that behavior doesn't mutate the state. For example, it may have a method that serializes itself.

DTO 是一种对象模式,用于在相关层之间传输状态。他们可以有行为(即技术上可以是 poco),只要该行为不会改变状态。例如,它可能有一个序列化自身的方法。

A POCO is a plain object, but what is meant by 'plain' is that it is not special. It just means it's a CLR object with no implied pattern to it. A generic term. It isn't made to work with some other framework. So if your POCO has [JsonProperty]or EF decorations all over it's properties, for example, then it I'd argue that it isn't a POCO.

POCO 是一个普通对象,但“普通”的意思是它并不特殊。它只是意味着它是一个没有隐含模式的 CLR 对象。一个通用术语。它不能与其他一些框架一起使用。因此[JsonProperty],例如,如果您的 POCO 的所有属性都带有EF 装饰,那么我认为它不是 POCO。

Here some examples of different kinds of object patterns to compare:

这里有一些不同类型的对象模式的例子来比较:

  • View Model: used to model data for a view. Usually has data annotations to assist binding and validation. In MVVM, it also acts as a controller. It's more than a DTO
  • Value Object: used to represent values
  • Aggregate Root: used to manage state and invariants
  • Handlers: used to respond to an event/message
  • Attributes: used as decorations to deal with cross-cutting concerns
  • Service: used to perform complex tasks
  • Controller: used to control flow of requests and responses
  • Factory: used to configure and/or assemble complex objects for use when a constructor isn't good enough. Also used to make decisions on which objects need to be created at runtime.
  • Repository/DAO: used to access data
  • 视图模型:用于为视图建模数据。通常有数据注释来帮助绑定和验证。在 MVVM 中,它还充当控制器。它不仅仅是一个 DTO
  • 值对象:用于表示值
  • 聚合根:用于管理状态和不变量
  • 处理程序:用于响应事件/消息
  • 属性:用作装饰来处理横切关注点
  • 服务:用于执行复杂的任务
  • 控制器:用于控制请求和响应的流程
  • 工厂:用于配置和/或组装复杂对象,以便在构造函数不够好时使用。还用于决定需要在运行时创建哪些对象。
  • Repository/DAO: 用于访问数据

These are all just objects, but notice that most of them are generally tied to a pattern. So you could call them "objects" or you could be more specific about its intent and call it by what it is. This is also why we have design patterns; to describe complex concepts in a few works. DTO is a pattern. Aggregate root is a pattern, View Model is a pattern (e.g. MVC & MVVM). POCO is not a pattern.

这些都只是对象,但请注意,它们中的大多数通常与模式相关联。所以你可以称它们为“对象”,或者你可以更具体地说明它的意图并按它的含义来称呼它。这也是我们有设计模式的原因;在一些作品中描述复杂的概念。DTO 是一种模式。聚合根是一种模式,视图模型是一种模式(例如 MVC 和 MVVM)。POCO 不是一种模式。

A POCO doesn't describe a pattern. It is just a different way of referring to classes/objects in OOP. Think of it as an abstract concept; they can be referring to anything. IMO, there's a one-way relationship though because once an object reaches the point where it can only serve one purpose cleanly, it is no longer a POCO. For example, once you mark up your class with decorations to make it work with some framework, it is no longer a POCO. Therefore:

POCO 不描述模式。它只是在 OOP 中引用类/对象的不同方式。把它想象成一个抽象的概念;他们可以指任何东西。IMO,虽然存在单向关系,因为一旦一个对象达到只能干净地服务于一个目的的地步,它就不再是 POCO。例如,一旦你用装饰来标记你的类以使其与某些框架一起工作,它就不再是一个 POCO。所以:

  • A DTO is a POCO
  • A POCO is not a DTO
  • A View Model is a POCO
  • A POCO is not a View Model
  • DTO 是 POCO
  • POCO 不是 DTO
  • 视图模型是一个 POCO
  • POCO 不是视图模型

The point in making a distinction between the two is about keeping patterns clear and consistent in effort to not cross concerns and lead to tight coupling. For example if you have a business object that has methods to mutate state, but is also decorated to hell with EF decorations for saving to SQL Server AND JsonProperty so that it can be sent back over an API endpoint. That object would be intolerant to change, and would likely be littered with variants of properties (e.g. UserId, UserPk, UserKey, UserGuid, where some of them are marked up to not be saved to the DB and others marked up to not be serialized to JSON at the API endpoint).

区分两者的重点是保持模式清晰和一致,努力避免交叉关注并导致紧密耦合。例如,如果您有一个业务对象,它具有改变状态的方法,但也使用 EF 装饰进行了装饰以保存到 SQL Server 和 JsonProperty,以便它可以通过 API 端点发回。该对象将无法容忍更改,并且可能充斥着属性的变体(例如 UserId、UserPk、UserKey、UserGuid,其中一些被标记为不保存到数据库,而另一些被标记为不序列化为API 端点上的 JSON)。

So if you were to tell me something was a DTO, then I'd probably make sure it was never used for anything other than moving state around. If you told me something was a view model, then I'd probably make sure it wasn't getting saved to a database. If you told me something was a Domain Model, then I'd probably make sure it had no dependencies on anything outside of the domain. But if you told me something was a POCO, you wouldn't really be telling me much at all.

因此,如果您告诉我某些东西是 DTO,那么我可能会确保它除了用于移动状态外,从未用于任何其他用途。如果你告诉我某个东西是一个视图模型,那么我可能会确保它没有被保存到数据库中。如果你告诉我某个东西是域模型,那么我可能会确保它不依赖于域之外的任何东西。但是,如果你告诉我某样东西是 POCO,你根本不会告诉我太多。