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