有啥理由将 POCO 变成 Model 对象?

Posted

技术标签:

【中文标题】有啥理由将 POCO 变成 Model 对象?【英文标题】:Is there any reason to make POCOs into Model objects?有什么理由将 POCO 变成 Model 对象? 【发布时间】:2011-07-25 11:11:33 【问题描述】:

如果我从 EntityFramework 生成 POCO 对象,并使用这些对象进出 WCF 服务器,是否有任何理由创建客户端模型以供视图和视图模型使用,而不是直接使用 POCO?

我看过的几乎所有 MVVM 示例都直接绑定到从 WCF 服务返回的对象。这是好习惯吗?是否可以为将 POCO 实际映射到模型并让 Views/ViewModels 使用 Model 对象而不是 POCO 进行论证?

我能想到的主要原因是验证,但是由于 EF POCO 是部分类,它们可以扩展为包括验证。

编辑

到目前为止,大多数答案都将INotifyPropertyChanged 作为构建单独模型的主要原因。如果您使用自我跟踪实体而不是已经包含INotifyPropertyChanged 的 POCO,您的答案会改变吗? STE 也是部分类,可以对其进行扩展以包括验证。

【问题讨论】:

自跟踪 EF POCO 可能没问题,但常规自跟踪实体仍将整个实体暴露给视图。我想我宁愿将它们存储在私有变量中,并根据需要将 ViewModel 属性映射到它们(不公开整个实体,只是我想要查看和更新​​的部分。我不知道,也许我也在制作太多了。 好的,我们在 WPF 应用程序中做了类似的事情,这个周末在南马里兰州 Give Camp。我们使用 Self-tracking entity T4 模板生成 POCO 实体类,并通过服务层公开它们。在实验中,我认为没有理由不直接使用 POCO。我们没有包装它们,而是创建了 Partial 类文件来根据需要增强它们。效果很好(有一些注意事项,比如终于意识到默认情况下,自我跟踪实体上没有启用“自我跟踪”)。 您在哪里进行验证?不要忘记模型上的 INotifyDataErrorInfo(如果您在 Reed 阵营,则为 ViewModel :D) 如果您正在做一些快速而简单的事情,并且您的视图对您的对象的要求不高,那么请务必使用它们——我自己经常这样做。然而,因为你永远不知道你的视图什么时候会被增强和复杂化——毕竟这就是 MVVM 的美妙之处——你最好为任何用于绑定到视图的重要对象创建好的丰富对象。那是因为你可能不再是未来编写视图的人,并在路上抱怨底层对象缺乏特征。 【参考方案1】:

验证是不直接绑定到 POCO 的主要原因。此外,如果 POCO 尚未实现 INotifyPropertyChanged 和其他必需的接口,则在 WPF 端使用对象的体验可能不太理想,并且实现一个 ViewModel 来包装它是有意义的。

提供一个 ViewModel 来包装您的 POCO 允许您将逻辑封装到 ICommand 实现中,并干净地实现所需的接口。

【讨论】:

@Rachel:他们通常会这样做 - 这需要通过网络推送,这可能会发生,也可能不会发生,这取决于您如何配置和创建 WCF 端点。它们不一定要实现INotifyCollectionChangedIDataErrorInfo 或其他接口(INPC 只是一个例子) @Reed 如果我的理解是正确的,您可以在 ViewModel 中公开 POCO 属性,而不是为它们创建单独的模型? @Rachel:是的,通常情况下,我会将通过网络连接的 POCO 视为“模型”,并制作一个 ViewModel 以将它们公开给 View。这几乎就是经典的 MVVM 风格。 @Reed 好的,谢谢。我对它的看法有点不同......我将模型作为它自己的一个类,并且 ViewModel 公开了一个可以绑定到的 Model 类型的属性 @Rachel:仅供参考 - 我在我的博客 (reedcopsey.com/series/windows-forms-to-mvvm) 中详细介绍了这一点,特别是在讨论“模型”以及此处的 MVVM 总结时:@ 987654322@【参考方案2】:

我对 Reed 的看法略有不同(当然,这是一种不寻常的情况)。我不会实现 ViewModel 来包装 POCO。我将实现一个模型类来包装 POCO 并通过服务层将模型公开给 ViewModel。

ViewModel 的主要工作是将模型数据适当地呈现给 View 并对其请求做出反应。我正在为此工作的架构如下所示:

每个 View 1 个 ViewModel ViewModel 调用数据服务层对象来检索模型实例(不要与 WCF 服务混淆) 数据服务层向后端发出适当的 CRUD 请求(这对 Silverlight 使用 WCF、RIA 或 RESTful 服务,但对于 WPF 可以直接使用 ADO.NET 或 EF)。 数据服务使用返回的 POCO 来创建模型对象。 模型对象包装 POCO 对象并实现 INotifyPropertyChanged。模型对象执行业务规则。

我仍在研究细节,但我会在不久的将来发布更具体的内容。

【讨论】:

@Joel 谢谢,这实际上是我现在的路线,尽管由于涉及额外的编码和类,有人提出了反对它的论点。大多数 MVVM 示例只是直接绑定到 WCF 对象并没有帮助。 是的,我同意乔尔的观点。不过,我大部分时间都喜欢 Reeds 的回答。来自我的+1,因为无论如何我们都有类似的答案。 ;) @Rachel 这无疑是额外的编码,但非常值得。我使用 CodeRush,它将扩展您的属性以自动包含 INotifyPropertyChanged 事件。它包含的数百个省时功能之一。 这是一个多一点的编码,但我认为长期的好处将超过麻烦。最有可能的是,使用 T4 模板,我们可以找到简化流程的方法。 我通常每个 View 有 1 个 ViewModel,但有时我会有两个不同的 View,它们以不同的方式显示相同的 ViewModel(DataGrid 和 DataForm)。我通过数据服务层调用数据提供者以防止混淆【参考方案3】:

我的模型接受一个 WCF 对象,该对象公开了我希望在我的 ViewModel 中使用的那些属性。然后我还可以根据需要扩展对象。我的属性指向 WCF 对象的属性,当我必须将对象发送回 WCF 服务时,我不必再做任何工作。模型继承了 DTO(此处称为 POCO)将没有的 INotifyPropertyChangedINotifyDataErrorInfo。您的业​​务逻辑/验证存在于您的 Silverlight 应用程序中,而不是您的 WCF 服务中。

视图绑定到具有模型(或模型的可观察集合)的视图模型。模型有一个 WFCObject,它是一个 DTO(这里称为 POCO)。我使用我的 ViewModel 与服务通信,MVVM Light 让模型与服务/提供者通信——我不喜欢。

【讨论】:

我喜欢这个想法,虽然我在客户端和服务器端都进行模型验证 有谁知道为什么 Reed 的答案比这样的答案更受欢迎?对我来说这不太有意义,因为就像他说的那样,WCF 对象不包含INotifiyPropertyChangedIDataErrorInfo,如果在多个视图中使用相同的模型,我觉得你最终会重复很多额外的代码在 ViewModel 中公开 WCF 对象的属性 这很好 - 但是,在经典的 MVVM 意义上,这个“模型”在技术上是一个 VM。您正在包装 DTO(实际上是模型)以提供验证等。 @Reed 我不同意。 Model 不是 ViewModel,因为它不与任何类型的 View 交互,也不包含任何将绑定到 View 的数据。它只包含与数据对象相关的数据 @Reed:我不同意。虽然 INotifyPropertyChanged 和 IDataErrorInfo 被 View 使用,但它们也有其他用途。我定期处理 PropertyChanged 事件以触发某些操作。 ViewModel 有一些东西供 View 与 Commands 和 PagedCollectionViews 交互。【参考方案4】:

如果您想做简单的 CRUD 或想要快速做某事,请绑定到 EF POCO。

否则,您的服务器端模型往往与数据库密切相关,与用户界面相比,数据库的变化非常缓慢。对于不那么琐碎的 UI,您会发现自己为了将数据库模型融入 UI 中而投入了越来越多的组件(否则,这会更糟)。

此外,还有性能问题(例如,您想在 UI 中只需要几个属性时传输整个实体吗?)和维护问题(例如,如果您想验证与普通客户完全不同的高级客户订单) .

另见http://ayende.com/Blog/archive/2010/08/06/data-access-is-contextual-a-generic-approach-will-fail.aspx

【讨论】:

【参考方案5】:

Rachel 的 POCO 只是由 EF 生成并用于传输 (DTO) 的哑对象。因此,他们不应该让其他事情弄乱他们的领域。这是设计代码的一种非常好的方式,因为它将任何客户端需求与服务器端的需求分离。这就是 MVVM 存在的原因 - 扩展包含这些问题的 MVC 模型。

只要不直接修改它们,就没有理由不能在视图中绑定它们。您可以通过添加部分类来为它们添加功能,但我什至不会这样做。在这种情况下,您应该遵循 MVVM 设计租户并将它们分离为满足您在客户端需求的模型对象。一旦你连接 INotifyPropertyChanged 事件来通知你的视图,这将是相当自动化的。

【讨论】:

我没有使用过 MVVM,我认为是在 MVC 中。 they shouldn't have other things cluttering up their model 是否仅适用于 MVVM?业务逻辑呢?还是被广泛认为属于不用作模型的领域对象? @StuperUser:不弄乱模型确实适用于所有架构模式,无论是 MVVM、MVC、MVP 还是其他。 @grrr:POCO 被归类为“哑”,因为它们不应包含除属性及其 getter/setter 之外的任何内容。它们非常适合往返于 WCF 服务的原因是它们在通过网络时体积小、重量轻。 我认为这个答案将 POCO 与 DTO 或类似的混淆了 我不明白为什么这个答案被否决:@philip 是绝对正确的。特别是在通过 WCF 传输的 EF POCO(我会让它们自我跟踪)的情况下,POCO 只是一种传输机制。业务层应该使用它并根据需要对其进行修改(CRUD),将业务规则应用于它。当然,这都是恕我直言。

以上是关于有啥理由将 POCO 变成 Model 对象?的主要内容,如果未能解决你的问题,请参考以下文章

POCO的解释

poco脚本编写

业务逻辑-Domain Model

.net中datatable和model有啥区别?

对象(poco)深度克隆

DTO DAO POCO BO