我正在使用 Microsoft 的 Entity Framework O/R 映射器,并将实体类(映射到 DB 对象的生成类)用作业务对象。这个可以吗?请说出你的缺点或优点。在业务层和表示之间进行WCF通信的情况下该怎么办,如何将这些对象作为数据成员发送?
7 回答
首先,在撰写本文时,有 11k 的问题视图,我对缺乏答案感到有点惊讶,恕我直言,答案的质量,给出了一个相当简单的问题。
所以,既然我已经发泄了一点,我想解决这个问题,因为我认为它在今天更适用于最近发布的 Entity Framework Code-First。
“使用实体框架实体作为业务对象?”
在我开始之前澄清几点:
当您说“业务对象”时,我的印象是您所指的这些对象包含规则或逻辑,例如从简单的验证(即必填字段)到更复杂的逻辑(即结账时的处理税)。
我认为我无法回答您关于 WCF 的后续问题。这样做的原因仅仅是因为我将客观地回答您关于 EF 作为业务对象的问题,然后主观地迫使我采取与我试图真实客观地回答所述第一个问题的尝试相矛盾的立场。
也就是说,将您的 EF 作为业务对象问题...
“我正在使用 Microsoft 的实体框架 O/R 映射器,并使用实体类(映射到 DB 对象的生成类)作为业务对象。可以吗?”
对不起,这里根本没有正确或错误的答案。这取决于您的目标是什么,以及在充分了解这样做的优缺点的同时,您得出的结论是最合理的设计。
“请说出你的优缺点”</p>
我很高兴你问!我很乐意回答,我希望在考虑到利弊的情况下,您能够就您是否认为将 EF 用于您的业务对象是“OK”做出明智的决定。通常情况下,我会列出利弊,以便于“消化”,但是,我认为这在这里不合适,因为我认为我们会对这样一个非常有趣的话题做出不公正的对待,而且也很接近和亲爱的我的心。
首先,让我从技术上谈一下……您可以将 EF 对象用作您的业务对象,没有什么技术上阻止您这样做。事实上,EF Code-First (CF) 通过允许您创建 POCO 并让您能够应用数据注释以进行简单验证以及实现 IValidatableObject 以进行更复杂的验证,从而使这非常容易。很酷,嗯?
讨论的核心就在这里。
EF 或任何 ORM 旨在支持数据管理。它的主要职责是数据,因此您创建的对象是以数据为中心的。所以,如果你也试图通过行为来设计你的对象,那么你手头就有一个难题。简而言之,这个难题被称为阻抗失配。想象一下;您的应用程序中有两个必需的用例:
- 编辑用户的屏幕
- 显示用户信息的只读子集的控件
如果使用 EF(任何风格)或任何 ORM,您可能会倾向于使用相同的“用户”对象来处理保存用户以及获取用户以提取只读字段子集的能力。您这样做可能是出于以下几个原因之一:
- 像许多开发人员一样,我们在教育过程中在我们的大脑中播下了这颗种子,“整合代码”是最重要的,或者可能更好地称为 DRY——不要重复自己,因此您可能会在消极的语境。
- 诸如 EF 4.1 之类的 ORM 具有技术限制(和骇人听闻的变通办法),例如将多个 POCO/对象映射到同一个数据库表,从而迫使您不管您的信念如何。
- 这是启动和运行应用程序的一种快速简便的方法
- 它“感觉”是正确的做法
这样做有好处也有坏处,你可以根据你的意见来看待这是积极或消极的方式。
我想如果你相信代码的规范化而不是行为,那么你已经取得了很大的成功。通过编写单个对象来处理该实体的数据和业务用例,您可以限制代码量,从而可能节省时间。
我想如果你相信代码行为的规范化,那么你就惨败了。通过节省代码,您已经牺牲了设计对象的职责,这可能会使其难以管理,从而增加维护成本。
不管您的意见如何,我们可能都同意这个业务对象承担了多项职责,并且对象的行为(不是数据!)充其量是次要的。它的主要职责是管理数据,次要职责是处理简单和复杂的业务规则,涉及编辑用户和显示只读用户信息。在面向对象设计 (OOD) 中,如果一个对象的设计以其身份和行为为特征,那么该对象可能是一个困惑的个体,因为它不符合 OOD 的定义。
从技术角度来看,任何时候您请求用户对象都会继承大量开销。当仅显示只读信息的子集时,这可能包括所有属性和业务规则等内容。
那么这一切与我是否应该使用 EF 来表示我的业务对象有什么关系呢?
嗯……虽然在技术上是可行的,但对于是否应该使用 EF 或任何 ORM 来表示您的业务对象,存在不同的理念(有些好,有些不好)。我针对上述这些哲学的核心给出了一个概要,但是 Rocky Lhotka 和 Martin Fowler 等人对它们进行了更详细的记录。
您采取的方向很可能取决于应用程序,从哲学角度来看,可能取决于您是理想主义者还是实用主义者。也就是说,我并不是说理想主义者或实用主义者与是否将 EF 用于业务对象相关——它只会影响您对此的看法。
在撰写本文时,Microsoft 的迹象表明 EF 是为处理业务逻辑而构建的,无论对错,它们似乎都朝着这个方向发展。EF 不断发展,某些技术限制正在被取消,因此 EF 最终可能被用于满足两全其美的需求。换句话说,最终你也许可以吃到你的蛋糕。
希望这可以帮助。
考虑到 ORM 背后的目的是管理数据,回答一个关于 ORM 的持久性无知是否荒谬的问题。:-) 对不起,我无法抗拒!
我以这种方式使用 EF,一个不错的特性是生成的实体是部分类,允许它们以一种不受再生问题影响的方式进行扩展。
还可以查看MSDN 上的此链接,该链接描述了 EF 在业务逻辑方面的一些常见使用场景。
根据我的经验,我们在应用程序的业务层中使用了 EF 对象,但是当我们通过 WCF 服务层过渡到表示层时,我们将从 EF 对象创建视图对象。
在我们的例子中,只有视图被传递到表示层。我们这样做是为了控制数据的呈现方式,并对来自表示层的数据应用防御性验证。
如果在 WCF 事务中使用 EF 对象,您将丢失与 EF 对象关联的对象上下文。CodePlex 有一些努力试图帮助解决这个问题,但我没有跟上他们的努力。
我遇到的两个限制是:
继承的对象不能有导航属性——即如果你有一个“人”类,然后是一个“客户”和“供应商”,这些客户和供应商不能有导航属性。
方法和计算字段(部分类中的任何内容)不会通过 ADO.Net 数据服务传输 - 如果您还使用 ADO.Net 数据服务,则您在部分类中扩展实体框架对象的任何内容都不会通过 ADO.Net 传输数据服务。
这些通常不是显示停止项(对于导航属性,我们暂时不使用实体框架上的继承),但您可能会感兴趣。我希望未来的版本能够启用这两个项目。
如果对象丢失了原始对象上下文,您就不能重新附加对象吗?不过,您需要自己处理并发问题。
我不建议将 EF 对象用作 WCF 的 DataContract 对象,因为您将实体对象的实现与 Web 服务客户端紧密联系在一起,将来很难进行更改,您计划拥有的客户端越多,就越难。
WPF 应用程序框架 (WAF)的 BookLibrary 示例应用程序展示了如何将模型-视图-视图模型 (MVVM) 模式与实体框架结合使用。