4

假设您有规范的客户域对象。您在三个不同的屏幕上显示客户:外部管理员、内部管理员和更新帐户。

进一步假设每个屏幕仅显示 Customer 对象中包含的所有数据的一个子集。

问题是:当 UI 从每个屏幕传回数据时(例如通过 DTO),它只包含完整客户域对象的子集。因此,当您将该 DTO 发送到客户工厂以重新创建客户对象时,您只有客户的一部分。

然后您将此客户发送到您的客户存储库以保存它,一堆数据将被清除,因为它不存在。悲剧接踵而至。

所以问题是:你将如何处理这个问题?

我的一些想法:

  • 在存储库中包含一个参数,指示要更新客户的哪一部分,并忽略其他部分

  • 当您加载客户时,将其保存在静态内存中、会话中或任何地方,然后当您从 UI 接收到其中一个 DTO 时,仅更新与 DTO 相关的部分

IMO,这两者都是kludges。还有其他更好的想法吗?

@chadmyers:这是问题所在。

实体具有属性 A、B、C 和 D。

DTO #1 包含 B 和 C 的属性。

DTO #2 包含 C 和 D 的属性。

UI 要求 DTO #1,您从存储库加载实体,将其转换为 DTO #1,仅填写 B 和 C,然后将其提供给 UI。

现在 UI 更新 B 并将 DTO 发回。您重新创建实体,它只填写了 B 和 C,因为这就是 DTO 中包含的全部内容。

现在您要保存仅填充了 B 和 C 的实体,其中 A 和 D 为空/空白。存储库无法知道它是否应该将持久性中的 A 和 D 更新为空白,或者是否应该忽略它们。

4

4 回答 4

4

在收到 DTO 后,我会使用工厂从存储库中加载完整的客户对象。之后,您只能更新在 DTO 中指定的那些字段。

例如,这还允许您通过检查最后更新的时间戳对您的客户应用一些乐观的并发性。

于 2008-10-23T21:48:46.447 回答
3

这是一个网络应用程序吗?从存储库加载客户对象,从 DTO 更新它,然后将其保存回来。这对我来说似乎不是一个杂物。:)

更新:根据您的更新(A、B、C、D 示例)

所以我在想的是,当你加载实体时,它已经填写了 A、B、C 和 D。如果 DTO#1 只更新 B 和 C,那没关系。A 和 D 不受影响(这是理想的情况)。

存储库如何处理 B & C 更新取决于他。例如,如果您使用的是 Hibernate/NHibernate,它只会弄清楚并发布更新。

仅仅因为 DTO #1 只有 B 和 C 并不意味着您也必须取消 A 和 D。不要管它们。

于 2008-10-23T21:43:11.780 回答
1

起初我错过了这个问题的重点,因为它基于一些我认为从设计角度来看没有意义的事情。

  1. 从存储库中水化一个实体,然后将其转换为 DTO 是浪费精力。我假设您的 DAL 将 DTO 传递给您的存储库,然后将其转换为完整的实体对象。因此将其转换回 DTO 似乎很浪费。

  2. 如果您的搜索结果页面显示大量记录并且仅显示部分实体数据,则拥有多个 DTO 是有意义的。在这种情况下,只传递该页面所需的数据是有效的。将包含部分数据的 DTO 传递给 CRUD 页面是没有意义的。只需给它一个完整的 DTO 甚至一个完整的实体对象。如果它不使用所有数据,很好,不会造成任何伤害。

所以主要问题是我认为您不应该使用部分 DTO 将数据传递到这些页面。如果您使用完整的 DTO,我会在执行保存操作时执行以下 3 个步骤:

  1. 从存储库或数据库中提取完整的 DTO
  2. 使用通过表单所做的任何更改更新 DTO
  3. 将完整的 DTO 保存回存储库或数据库

此方法需要额外的数据库命中,但这在 CRUD 表单上确实不是一个重要问题。

于 2009-02-10T04:47:58.517 回答
1

如果我们了解存储库(几乎完全)处理非常丰富的域实体,那么您众多的 DTO 可以简单地映射回来。

IE

dtoUser.MapFrom<In,Out>(Entity)
or
dtoAdmin.MapFrom<In,Out>(Entity)

您将执行相反的操作以将 dto 信息返回给实体,依此类推。所以你的存储库只保存了丰富的实体而不是大量的 DTO

entity.Foo = dtoUser.Foo
or
entity.Bar = dtoAdmin.Bar

entityRepsotiry.Save(entity) <-- do not pass DTO.

DTO 的全部意义在于使演示文稿保持简单,或者说 WCF 数据传输,它与存储库或实体无关。

此外,您永远不应该从 DTO 构造实体......获取实体的唯一两种方法是分别通过工厂(新)或存储库(现有)。

您提到将实体存储在某个地方,您为什么要这样做?那是您的存储库的工作。它将决定从哪里获取实体(数据库、缓存等),无需将其存储在其他地方。

希望这有助于在您的域中分配责任,这始终是一个挑战,并且到处都有灰色区域,但总的来说,这些是存储库、DTO 等的典型用途

于 2009-05-25T00:12:12.297 回答