70

我偶然发现了以下两篇文章FirstSecond,其中作者总结指出 ORM Entities 和 Domain Entities 不应混淆。

当我使用代码优先方法使用 EF 6.0 进行编码时,我现在正面临这个问题。我将 POCO 类用作 EF 中的实体以及我的域/业务对象。但是我发现自己经常处于将属性定义为公共属性或将导航属性定义为虚拟属性的情况,这仅仅是因为 EF 框架强制我这样做。

不知道拿什么作为两篇文章的底线?例如,我是否应该为实体框架创建一个 CustomerEF 类,为我的域创建一个 CustomerD。然后创建一个使用 CustomerD 的存储库,将其映射到 CustomerEF 做一些查询,然后将收到的 CustomerEF 映射回 CustomerD。我认为 EF 就是将我的域实体映射到数据。

所以请给我一些建议。我是否忽略了 EF 能够为我提供的重要内容?或者这是一个EF无法完全解决的问题?在后一种情况下,解决这个问题的好方法是什么?

4

1 回答 1

85

我同意这些帖子的总体思路。ORM 类模型首先是数据访问层的一部分(即使它由所谓的 POCO 组成)。如果持久性和业务逻辑(或任何其他问题)之间出现任何利益冲突,则应始终做出有利于持久性的决策。

然而,作为软件开发人员,我们总是要在纯粹主义和实用主义之间取得平衡。是否将持久性模型用作域模型取决于许多因素:

  • 开发团队的规模/连贯性。当整个团队都知道属性可以仅仅因为 ORM 要求而公开,但不应该到处设置时,这可能没什么大不了的。如果每个人都知道(并遵守)ID 属性不能用于业务逻辑,那么拥有 ID 可能没什么大不了的。分散、缺乏经验或无纪律的团队可能需要更严格的代码隔离。

  • 业务逻辑关注点和持久性关注点之间的重叠。当类模型坚持SOLID原则时,面向对象的设计就会蓬勃发展。但这些原则不一定与持久性问题相矛盾。我的意思是,尽管关注点不同,但最终它们产生的要求可能非常相似。例如,这两个问题都可能需要有效的对象状态和正确的关联。

    但是,可能存在一些用例,其中对象暂时需要处于绝对不应该存储的状态。这可能是使用专用域类的原因。另一个原因可能是实体模型无法实现最佳的职责分割。例如,“将客户列入黑名单”的业务流程可能需要分散在许多实体对象中的数据,因此必须设计新的域类来封装数据和处理这些数据的方法。换句话说:实体这样做会违反告诉不问原则。

  • 需要分层。例如,如果数据访问层针对不同的数据库供应商,它可能必须由特定于供应商的可互换部分组成(例如,考虑到 Oracle 和 Sql Server 之间数据类型的细微差异或利用供应商特定的功能)。使用持久性模型作为域模型可能会将特定于供应商的实现引入业务逻辑。那真的很糟糕。那里的数据访问层应该就是那个层。

  • (非常琐碎)数据量。创建对象需要时间和资源。当业务案例中涉及“许多”对象时,构建实体对象和域对象可能过于昂贵。

还有更多,毫无疑问。

所以我会一直努力做一个实用主义者。如果实体类做得不错,那就去做吧。如果不匹配太大,请为业务逻辑的适当部分创建业务域。我不会仅仅因为它是一个好的模式就盲目地遵循(任何)设计模式。与帖子中所说的相反,将实体模型映射到业务模型需要大量维护。当您发现自己创建了无数与实体类几乎相同的业务类时,是时候重新考虑您在做什么了。

于 2013-08-07T20:52:40.280 回答