从多个DTO构造域对象

时间:2008-10-23 21:32:19

标签: repository-pattern dto domain-object

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

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

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

然后您将此客户发送到您的客户存储库以保存它,并且一堆数据将被清除,因为它不在那里。随之而来的是悲剧。

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

我的一些想法:

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

  • 当您加载客户,将其保存在静态内存中,或在会话中或任何地方,然后当您从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 个答案:

答案 0 :(得分:4)

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

例如,通过检查上次更新的时间戳,您还可以对客户应用一些乐观并发。

答案 1 :(得分:3)

这是一个网络应用程序吗?从repo加载客户对象,从DTO更新它,然后保存回来。这对我来说似乎不是什么好事。 :)

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

所以我想的是当你加载实体时,它填充了A,B,C和D.如果DTO#1只更新B& C,没关系。 A和D不受影响(这是所希望的情况)。

存储库对B& S的影响。 C更新取决于他。例如,如果您正在使用Hibernate / NHibernate,它只会解决问题并发布更新。

仅仅因为DTO#1只有B& C并不意味着你也必须将A& D.别管它们。

答案 2 :(得分:1)

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

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

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

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

    1. 从存储库或db
    2. 中提取完整的DTO
    3. 使用表单
    4. 所做的任何更改来更新DTO
    5. 将完整的DTO保存回存储库或db
    6. 此方法需要额外的数据库命中,但这在CRUD表单上确实不是一个重要问题。

答案 3 :(得分:1)

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

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 dataTransfer,它与存储库或实体无关。

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

你提到将实体存储在某处,为什么要这样做?这是您的存储库的工作。它将决定在何处获取实体(db,cache,e.t.c),无需将其存储在其他地方。

希望有助于在您的域中分配责任,这总是一个挑战,并且这里和那里都有灰色区域,但一般来说,这些是Repository,DTO e.t.c的典型用途。