实体框架6.0下的ORM实体与域实体


69

我偶然发现了以下两篇文章,第一篇和第二篇,作者在摘要中指出,不应将ORM实体和域实体混淆。

当我使用“代码优先”方法使用EF 6.0进行代码编写时,我正好面对此问题。我将POCO类用作EF中的实体以及域/业务对象。但是我经常遇到这样的情况,我将一个属性定义为public或将一个导航属性定义为virtual只是因为EF Framework迫使我这样做。

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

因此,请给我一些建议。我是否忽略了EF能够为我提供的重要信息?还是这是EF无法完全解决的问题?在后一种情况下,什么是解决此问题的好方法?


1
只是一个不起眼的提醒,你的“第一”和“第二”链接不工作的时刻
哈姆扎Khanzada

有关第一篇和第二篇文章的新链接。
莱昂纳多·卢西

Answers:


80

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

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

  • 开发团队的规模/一致性。当整个团队都知道仅出于ORM要求就可以公开属性,但不应在各处设置属性时,这可能并不重要。如果每个人都知道(并服从)ID属性不会在业务逻辑中使用,那么拥有ID可能并不重要。分散,没有经验或没有纪律的团队可能需要更严格的代码隔离。

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

    但是,在某些用例中,对象暂时需要处于绝对不应存储的状态。这可能是使用专用域类的原因。另一个原因可能是实体模型无法完全履行职责的最佳划分。例如,业务流程“将客户列入黑名单”可能需要分散在如此众多实体对象上的数据,因此必须设计新的域类,以封装数据及其上使用的方法。换句话说:由实体执行此操作将违反“告诉不要问”的原则。

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

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

无疑还有更多。

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


19
好答案。我特别喜欢您关于成为实用主义者的言论。设计模式应达到目的,它本身不应成为目标。
Jowen 2014年

很好的答案,我想知道是否有一种方法可以通过使用internal关键字隐藏外键属性来同时实现(纯粹主义和实用主义)。
卡夫·哈贾里

1
@KavehHadjari。当然,这是有可能的(EF甚至可以处理私人成员)。同样可以用做没有直接业务相关的属性,如InsertDateTime,等
格特·阿诺德

“软件开发人员我们总是必须在纯粹主义和实用主义之间取得平衡。” 值得引用。
adnanmuttaleb
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.