面向对象的设计:保存复杂的对象

时间:2009-11-12 17:05:06

标签: oop

我有一个基于遗留系统构建的复杂域模型,我已经构建了大多数“get”方法 - 通常只是传递数据库主键ID。很容易。我现在好奇如何处理在数据库中创建新对象的任务,并用新数据保存现有对象,并希望确保我覆盖所有基础。

对应于整个项目中数据库中实体的主域对象,大约20-25。需要保存大约10个左右(其余的只是用于支持数据而不需要用户更新)。要保存的对象具有复杂的依赖关系 - 对象A有一个对象B列表,其中包含对象C,D和E,例如,当原始对象A出现时,所有这些对象都可能需要保存。

我想构建它以便UI开发人员可以轻松使用它,但也强制只保存有效数据(假设对象B无法保存,除非对象C处于有效状态)。这让我不愿意让他们从头开始创建一个对象并尝试保存它 - 我想遵循这样的原则:对象应该只在有效状态下存活。

另一种选择是在处理它们的服务对象上公开“CreateNew”和“Save”方法,但这些方法的参数列表会很恶劣。

我正在考虑要求“CreateNew”和“Save”来接受他们可以创建和传递的命令对象之类的东西,以便他们确切地知道需要什么数据以及他们无法控制什么。我读了command pattern,但我不需要它提供的任何主要优惠。

我应该考虑哪些方法来决定?这是C#3.5,如果它完全归因于它。

2 个答案:

答案 0 :(得分:1)

你可以让你的对象都暴露相同的方法,称之为AttemptSave,并在父对象上调用这个方法将导致它调用所有子节点的那些方法。

该方法可以返回一个布尔值,表示操作成功。无需抛出异常即可让UI开发人员轻松使用。

然后公开方法GetValidationErrors。如果AttemptSave返回false,则UI开发人员应调用此方法来检索并显示错误。

或者,您可以添加验证方法验证,该验证方法将预先检查对象层次结构。您可以通过GetValidationErrors返回验证错误。然后将执行对AttemptSave的调用。如果失败,您可以使用GetOperationErrors返回错误。

SQL哲学中的一些东西。无论您的查询成功与否,您都可以随时查看@@ ROWCOUNT,以了解查询是否至少完成了部分工作。

答案 1 :(得分:1)

您应该研究.NET的流行对象关系映射框架。很多人以前都处理过这个问题,而一些最聪明的人已经和我们分享了他们的劳动成果。它们有很多功能,而且最受欢迎的功能都经过严格测试。

似乎每隔几天,有人会问新的.NET ORM建议,因此有很多Stack Overflow主题可以帮助指导您。例如:

(如果您搜索'ORM'和'.NET',您将会收到更多匹配。)

在典型用法中,UI开发人员只处理高级父对象(在域驱动设计语言中称为“聚合根”)。他们将ORM用作Repository,并确保给定保存中的所有操作在合理的事务中捆绑在一起。 (您仍需要在域对象中按照业务规则强制执行有效性。)

以下简要介绍了UI代码的外观:

// Given an IRepository implemented by your ORM,
ICustomer customer = repository.Get(customerId);

// ... do stuff to customer and its child objects ...

repository.Save(customer);