在三层项目中放置 DTO / POCO

Posted

技术标签:

【中文标题】在三层项目中放置 DTO / POCO【英文标题】:Placement of DTO / POCO in a three tier project 【发布时间】:2012-07-16 07:08:07 【问题描述】:

我一直在为网站重新编写后端,并一直在将其移向三层架构。

我的意图是这样构建它:

Web site <--> WCF Service (1) <--> Business Layer (2) <--> Data Layer (3)

我的问题是 DTO 在这个结构中的位置。我需要使用 DTO 在业务层和 WCF 服务之间以及从 WCF 服务到消费网站之间移动数据。

在我对这里的研究期间,我阅读了一些很棒的讨论,尽管我有点摸不着头脑:

Davide Piras 在this post 中提出了一些重要观点,如果我要遵循这个设计,那么我会在一个单独的项目中声明 POCO 的接口。然后,这些将由层 (1) 和 (2) 实施。虽然我喜欢使用接口,但通过在 (1) 和 (2) 中声明 POCO,然后使用 AutoMapper 之类的东西来回复制它们的数据,我似乎确实可以为自己做更多的工作。

李>

This post 使用一个系统,其中创建了一个业务对象项目,该项目将被所有层引用。这似乎比其他解决方案更简单,并且似乎引导我找到一个解决方案

Web site <--> WCF Service (1) <--> Business Layer (2) <--> Data Layer (3)

^               ^                       ^
|               |                       |
[ -- Business Objects Referenced here --]

我的问题是:跨解决方案的三层共享业务对象是否会产生代码异味,还是我上面列出的两种方法只是破解同一个问题的两种不同方法?

【问题讨论】:

好问题。措辞和研究。我大约 2 天后才能提出这样的问题,但它帮助解决了一些难题。听起来有点像“Ka-Chung,Ka-Chung!” 【参考方案1】:

让我们将您的 UI(网站)和服务(WCF + BL + DAL)视为两个不同的实体。

如果您对两者都有 100% 的控制权,则应选择方法 #2,因为它会避免 WCF 代理对象和 UI 层中的业务对象之间的转换。

否则,您最好使用方法 #1,因为其中一个实体是一种“黑匣子”,并且会受到外部利益相关者的更改。因此,维护一组内部业务对象更安全。这需要在您的业务对象和 WCF 代理对象之间进行转换(通过扩展方法或转换器框架)。

现在,不能完全确定您的 UI 层复杂性或其实现(MVC、WebForms 等),因此您可能需要也可能不需要 View 特定对象(更轻的数据绑定、更快地序列化为 JSON 等)。 ),我们称这个对象为Model

如果您不需要特定的 UI 特定 Model,建议将您的业务对象标记为 DataContract(在 WCF 的上下文中)并跨层使用它们。如果您通过 Web ($.ajax) 调用 WCF,请不要忘记将实体显式标记为 Serializable

否则,在服务中使用DataContract,并在 UI 层使用转换器将DataContract 转换为ModelService Adapter 非常适合这里 - 它位于 UI 层,负责使用 WCF 服务并在 DataContractModel 之间进行转换。您可以在 UI 层中使用 Service Proxy,它是您的 WCF 服务的包装器,可在 Web 上使用。

最后,您是否缺少对数据层中业务对象的引用?我相信您会从数据层本身的数据存储中填充您的业务对象。

【讨论】:

感谢您抽出宝贵时间回复。我想我正在转向方法#2,正如你所说的那样,我可以控制网站和后端,而且它不是一个大型网站,我会为自己做更多的工作,而使用方法#1 几乎没有什么好处。该站点不是 MVC,只是普通的 Web 表单。从长远来看,我可能会将其移至 MVC,并且我没有考虑过这是否会影响它。我会记住你说的话,干杯! 关于数据层和业务对象引用,我的数据层只是暴露了一个静态类,允许业务层访问数据库。看着它,我这样做可能混淆了两层之间的界限。【参考方案2】:

我想说这通常取决于您正在构建的项目的复杂性。对于我构建的较小项目,我在各个层之间共享我的“实体”(它们只是简单的 DTO,带有 getter 和 setter 的可序列化数据桶),并不太关心这一点。最大的缺点是逻辑分散在整个项目中(不仅在“业务层”中)并且到处都是程序风格。这看起来确实像贫血领域模型,但由于项目没有增长太多,复杂性并没有蔓延。实体框架有一些模板,您可以以此构建实体(如果我没记错的话,它们被称为自我跟踪实体?)。

对于中型/大型项目,我不会使用这种方法,而是将实体和 DTO 分开,因为它们将扮演不同的角色。 DTO 可能具有与您的实体完全不同的形状,并且尝试在层/层之间共享它们通常会很臭。

【讨论】:

感谢您的意见。在查看这两种方法时,我没有考虑项目的规模。由于该网站不是一个庞大的网站,并且大部分增长可能会重新使用现有对象,我可能会转向共享业务对象。

以上是关于在三层项目中放置 DTO / POCO的主要内容,如果未能解决你的问题,请参考以下文章

在三层交换机S1上配置vlan10、20,在三层交换机S2上配置vlan30、40,启用三层路由功能(启用RIPv2)

在三层交换机上实现DHCP中继实验二

利用三层交换机实现VLAN间路由

事务管理在三层架构中应用以及使用ThreadLocal再次重构

实验五:利用三层交换机实现VLAN间路由

实验五利用三层交换机实现VLAN间路由