2

可能重复:
使用实体框架实体作为业务对象?

我正在研究将实体框架用作 ORM,但在阅读了大量内容后,我对 EF 对象的确切位置感到非常困惑。

我的印象是,ORM 的全部意义在于消除将对象映射到关系数据库的繁琐和复杂的工作。你加载你的数据库并得到一堆像魔法一样的对象。CRUD 的东西都是针对对象完成的。如果数据库发生更改,您将更改映射但您的对象保持不变。

这意味着您将在整个系统中使用这些对象,并且它们将具有行为。它们是业务对象。这对我来说很有意义,而且确实 MS告诉你如何添加行为

但是,我一直在阅读很多人说您永远不应该将 EF 对象用作您的业务对象,因为他们只关心数据的持久性,并且会将您的业务对象与 EF 耦合。他们建议使用 EF 作为数据层的抽象,并将它们映射到真实的业务对象。

这对我来说似乎毫无意义。当我仍然最终映射到我的业务对象时,为什么还需要另一个抽象层?如果我必须映射 EF 属性,我不妨映射 DB 列!

我认为 ORM 的全部意义在于自动化映射并充当后备存储的抽象?我错过了什么吗?

编辑:行为我的意思是业务逻辑。验证、计算属性、业务方法等。

4

2 回答 2

2

一般来说,那些说你不应该使用 EF 生成的类作为业务层的人是正确的。

不过,在小型应用程序中,您绝对可以直接从 UI 中使用 EF 类。

随着您的应用程序的大小和功能不断增长,您肯定会在 UI 中使用 EF 类时遇到问题:选择 N+1(视图中发生延迟加载)、序列化(循环引用)、AJAX/jQuery(发送过大的对象用于微小更新场景的在线图表)等。

人们经常推荐使用 AutoMapper(https://github.com/AutoMapper/AutoMapper)在你的 EF 类和 DTO 类和业务层类之间进行映射,以减少编写大量映射代码的乏味。

我认为这绝对是您可以根据您的项目要求做出的决定,不一定有正确的答案。如果您开始感到疼痛,您可以随时改变方向。与往常一样,选择对您的项目可行的最简单的解决方案。

于 2012-08-07T11:36:18.613 回答
1

如果数据库发生更改,您将更改映射但您的对象保持不变。

不会。Db 更改也会更改映射的实体类。但这并不意味着这些类不能用于业务逻辑。如果您使用开箱即用的 EF,它将创建实体类作为partial类,因此邀请您以不会被生成的代码覆盖的方式添加自己的代码。

人们说 (...) [EF 对象] 只关心数据的持久性

我不这么认为。它们可能能够被持久化到数据存储并从数据存储中填充(就像它们在数据库优先工作时一样),但这不是它们关心的问题。我们应该忽略这种添加的行为,而不是在业务逻辑中使用它(我认为)。对象不是持久性无知的,业务逻辑应该是。

话虽如此,我一直将实体类用于业务逻辑。但我不再是纯粹的 OO 的粉丝,在密切合作的对象与精心分离的职责的意义上。有两个原因:

  1. 大多数应用程序都涉及某种业务层和带有视图模型的视图层,它们由控制器层粘合在一起,并通过需要序列化的边界进行通信。所以直接调用领域类的行为通常不是一种选择。因此,我倾向于在通过 DTO 进行通信的服务类或外观中编写越来越多的 BL,而在直接从其他层解决的领域模型中编写更少的 BL。这些服务方法往往是业务逻辑的完美场所。所以大多数时候,我扩展 EF 类的逻辑涉及到类本身的数据,并且不需要与其他 EF 类进行任何合作。这也可以防止延迟加载异常和 n+1 问题。我可以展示很多例子,我很乐意在服务方法中从域逻辑转移到 BL,但那

    同样,我不喜欢使用OnPropertyChanging/Changed其中一个 MS 链接描述的方法。我已经做到了,它是意大利面。它在视图模型中很有用,例如响应用户输入,但在域类中设置属性应该是:设置属性。没有添加的行为会被遗忘并且有一天会咬你。

  2. (无状态)函数式编程范式的进步,受到 Linq 和其他 .Net 语言结构的鼓励。

所以我看到我的领域模型越来越接近贫血的领域模型,尽管从未真正到达那里。我试图给出一些理由,为什么这在今天是完全明智的。

于 2012-08-06T14:45:02.647 回答