【问题标题】:Logic involving processing on data (from DB) in ViewModel or Model?涉及在 ViewModel 或 Model 中处理数据(来自 DB)的逻辑?
【发布时间】:2011-05-26 11:53:07
【问题描述】:

我正在使用 WPF 开发应用程序。我使用的模式显然是 MVVM。此外,我正在使用实体框架 ORM 和 LINQ-to-Entities 来查询 EF 对象。

我对 MVVM 的理解是 View 不应该有代码隐藏,它应该拥有的 ViewModel 的唯一知识是 ViewModel 包含与 View 绑定的某些属性,并且它还包含处理视图事件的命令.而模型只包含从数据库中获取数据的代码。

在我的模型类中,我刚刚编写了使用 Linq-to-entities 直接查询 EF 对象的函数。在将数据分配给 VM 中的属性之前,我需要对数据执行的处理要么存在于 VM 中,要么存在于 VM 项目中的类中。在这里提一下,我有 3 个项目 - View、ViewModel 和 Model。

我的问题是,我可以将这些功能(涉及处理数据库中的数据)保留在 VM 项目中还是应该保留在模型项目中?如果在 ViewModel 项目中,它应该在相关的 VM 中还是在 VM 项目中存在的单独类中?

【问题讨论】:

    标签: wpf entity-framework mvvm linq-to-entities


    【解决方案1】:

    一种常用的做法是将业务逻辑委托给服务层,并使用存储库模式执行业务逻辑。正如其他答案中提到的,ViewModel 应该使用处理 UI 交互的视图特定属性和命令来装饰模型。根据它自己的定义,模型应该具有处理数据的所有逻辑。

    如果您遵循面向服务的架构,则可以向 ViewModel 注入服务。该服务负责执行业务功能。这些业务功能大多是在持久化数据上完成的。并且可以使用任何 ORM 工具和技术(如 EF 或 NHibernate)很好地抽象该逻辑。如果您遵循此架构,您可以在 Google 上搜索 Repository Pattern,这会很有帮助。

    如果您不需要,则不必使用存储库模式。您仍然可以直接从服务层使用 EF。拥有存储库的优势在于它充当持久层(数据库)和域层(模型)之间的映射器。

    希望这会有所帮助。

    【讨论】:

    • 感谢您的详细回复
    【解决方案2】:

    它们应该在 Model 项目中,ViewModel 只是您的 View 期望的表示,仅此而已。

    【讨论】:

      【解决方案3】:

      职责是: 模型 -> 从数据库、服务等获取数据并通过域对象公开数据。不关心数据将如何显示。只关心涉及领域对象的业务逻辑。

      ViewModel -> 从模型中读取数据并装饰它们,以便它们可以以正确的格式显示在视图中。公开视图可以绑定以获取数据的属性。同时公开视图可以在用户输入上调用的命令。

      查看 -> 根据通过 DataBinding 从 VM 接收的数据,使用漂亮的 DataTemplate 或 UserControl 显示数据。绑定到 VM 命令以调用用户输入。

      理想情况下,ViewModel 只关心在 UI 上显示数据,而不关心修改模型。它在其构造函数中接收模型对象,并通过数据绑定公开要由视图使用的属性。模型不知道 ViewModel。每当模型数据发生更改时,ViewModel 都可以通过 VM 订阅的模型引发的事件来通知更改。或者,每当 View 调用 VM 中的属性 getter 获取数据时,VM 都必须查询模型。

      无论属性如何显示,模型都应公开属性。所以它不应该对属性做任何处理。 ViewModel 可以根据 View 的要求装饰从 Model 接收到的数据。

      【讨论】:

      • “每当模型数据发生变化时,ViewModel 都可以通过 VM 订阅的模型抛出的事件来通知变化”。你能举例说明这一点吗?如果 ViewModel 不能修改数据,Model 也不能对数据做任何处理,那这个逻辑应该放在哪里呢?
      • 模型应根据业务逻辑更改其自身的数据。每当它更改其数据时,它都可以引发事件以通知 VM 数据更改。如果 VM 需要更改这些数据以便更好地显示,它应该将模型中的数据读取到自己的字段中,更改它并通过属性公开更改的数据。 VM 不应更改模型数据。它只关心数据的外观,与业务逻辑无关。
      【解决方案4】:

      在我看来,最好将数据库处理功能移至 Model 项目,因为 ViewModel 可能会承担太多责任。

      我将尝试展示一个示例:

      假设我们有一个类SomeViewModel,其属性为IsHighlitedItem,如下所示:

      class SomeViewModel
      {
          public bool IsHighlighted
          {
              get 
              { 
                  /* View logic here */
              }
          }
      
          public SomeClass Item
          {
              get
              {
                  /* Retreiveing an item from database */
              }
          }
      }
      

      现在当你需要修改一个视图逻辑时你必须修改SomeViewModel这个类(没关系),但是当你需要修改一个数据库通信逻辑时你也需要修改同一个类,这还不是很好.

      Single responsibility principle 说:

      不应该超过一个 更改课程的原因。

      因此,如果您保持现状,将来可能会遇到不必要的代码复杂性。

      【讨论】:

        【解决方案5】:

        您可能对 WPF Application Framework (WAF)BookLibrary 示例应用程序感兴趣。它展示了如何将实体框架与 MVVM 模式一起使用。

        【讨论】:

        • 这里没有尝试回答这个问题,还有另一个地方可以让你链接你的 WAF。您甚至没有链接到网站上任何特定的、有用的页面。
        猜你喜欢
        • 1970-01-01
        • 2018-04-11
        • 1970-01-01
        • 1970-01-01
        • 2011-05-26
        • 2018-11-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多