Entity Framework 6.0下的ORM实体和领域实体

74
我偶然发现以下两篇文章第一篇第二篇,总结说ORM实体和领域实体不应混淆使用。
我目前在使用EF 6.0的Code First方法编写代码时也遇到了这个问题。我将POCO类用作EF中的实体以及我的领域/业务对象。但是我经常发现自己定义一个属性为public,或者将导航属性定义为virtual,只是因为EF框架强制我这样做。
我不知道这两篇文章的底线是什么?我真的应该为实体框架创建一个CustomerEF类和一个CustomerD类,并创建一个消耗CustomerD并将其映射到CustomerEF进行一些查询,然后将接收到的CustomerEF映射回CustomerD的存储库吗?我认为EF主要就是将我的领域实体映射到数据上。
所以请给我一些建议。我是否忽略了EF能够为我提供的重要内容?还是说这是一个EF无法完全解决的问题?在后一种情况下,如何有效地管理这个问题呢?

1
只是一个谦虚的提醒,您的“第一”和“第二”链接目前无法使用。 - Hamza Khanzada
新链接关于第一篇第二篇文章。 - Leonardo Lurci
这篇文章有些古老,但仍然有效。 - Ralf
1个回答

90

我赞同这些文章的一般想法。ORM类模型首先是数据访问层的一部分(即使它由所谓的POCOs组成)。如果持久性和业务逻辑(或任何其他关注点)之间存在利益冲突,则应始终做出有利于持久性的决策。

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

开发团队的规模/协作性。当整个团队都知道属性可以公开仅仅是为了ORM要求,但不应该随处设置时,这可能不是什么大问题。如果每个人都知道(并遵守),ID属性不应在业务逻辑中使用,那么拥有ID可能也不是什么大问题。一个分散的、没有经验或纪律性不强的团队可能需要更严格的代码分离。
业务逻辑关注点与持久化关注点之间的重叠。面向对象设计在类模型遵循SOLID原则时得到优化。但这些原则不一定与持久性关注点相矛盾。我的意思是,尽管这些关注点是不同的,但它们最终的要求可能非常相似。例如,这两个关注点都可能需要有效的对象状态和正确的关联。
然而,可能存在使用案例,在这些案例中,对象暂时需要处于不能存储的状态。这可能是使用专用领域类的原因。另一个原因可能是实体模型无法实现最佳的责任分割。例如,业务流程“列入客户黑名单”可能需要数据分散在许多实体对象上,必须设计新的领域类来封装数据和处理它们的方法。换句话说:如果使用实体来执行此操作,将违反Tell Don't Ask原则。
需要分层的需求。例如,如果数据访问层针对不同的数据库供应商,则必须由供应商特定的可互换部件组成(例如,为了考虑Oracle和Sql Server之间数据类型的微小差异或利用供应商特定的功能)。使用持久性模型作为领域模型可能会将供应商特定的实现渗入业务逻辑中。那将是真的很糟糕。在这里,数据访问层应该恰好是一个层。
(非常琐碎)数据量。创建对象需要时间和资源。当在业务案例中涉及到“许多”对象时,构建实体对象和领域对象可能太昂贵。
"And more, undoubtedly."(更多的,毫无疑问。)
因此,我总是尽力成为一个实用主义者。如果实体类做得不错,就使用它们。如果不匹配太大,为适当的业务逻辑部分创建业务域。我不会因为某个设计模式很好而盲目地遵循它。与帖子中所说的相反,将实体模型映射到业务模型需要大量维护。当你发现自己正在创建许多与实体类几乎相同的业务类时,就该重新考虑你正在做什么。"

22
好的回答。我特别喜欢你关于成为实用主义者的评论。设计模式应该有一个目的,而不是成为自身的目标。 - Jowen
不错的答案,我想知道是否有办法通过使用内部关键字来隐藏外键属性,从而实现两全其美(纯粹和实用主义)。 - Kaveh Hadjari
1
@KavehHadjari。当然,这是可能的(EF甚至可以处理私有成员)。对于像InsertDateTime等不直接与业务相关的属性也可以这样做。 - Gert Arnold
1
作为软件开发人员,我们总是需要在纯粹主义和实用主义之间取得平衡。这句话值得引用。 - adnanmuttaleb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接