领先技术

数据建模的对象和艺术

Dino Esposito

 

Dino Esposito
许多当今的应用程序将围绕单个数据模型中,通常保存到数据存储区通过对象关系映射器 (ORM) 工具而构建。但有时 — 原因有多种不同 — — 可能需要更多的灵活性,这需要多个模型。在本文中,我将介绍一些可用于处理这些情况和开发多个分层和可靠的应用程序的策略。

清楚地使用不同的模型使得整个应用程序较为复杂,但它是一种如有必要,正使整个项目更易于管理的复杂性。了解当一个模型的数据只是不适合所有用例是体系结构设计者面临的挑战。

软件应用程序的不同部分可能有他们自己的数据模型。在其中您来表示用户界面级别上的数据的方法是不同于在其中组织的中间层中的数据的方式,它可能甚至是从物理上某些数据存储区中保持数据的方式不同。

但是,许多年来,开发人员使用的数据,而不用考虑所涉及的应用程序的一部分的只是一个模型。许多人已增长与关系数据库和其相关的建模技术。它是我们自然而然地花费大量精力来详细描述基于关系和规范化规则的模型。存储在关系数据库中的所有数据然后都被提取并移使用内存结构类似于内存中的数据库。记录集是此通用数据模式的名称 (请参阅 bit.ly/nQnyaf); ADO。NET 数据集时它的出色实现。

基于表的方法已逐渐推送到角由应用程序的日益增长的复杂性。ORM 工具兴起的两个主要的实际原因。首先,使用对象是更容易处理的数据 (如记录集的泛型 super-arrays。第二个原因是生产效率。ORM 的目标是采取一个对象模型,将它映射到关系的架构。通过使用 ORM,实质是生成到应用程序的眼睛看起来像实际的数据库的对象模型。

您如何设计此模型?并应真正使用只有一个模型的每个应用程序吗?让我们来了解一下。

一个模型始终无法容纳所有

为"第一个代码"编程中,其名称所暗示的最近发布的实体框架 (EF) 4.1 包含支持,可以让 Microsoft。NET 框架开发人员采用数据建模代码第一位的做法。从根本上说,这意味着您开始通过编写模型的应用程序域的普通旧 CLR 对象 (POCO) 类。第二个步骤组成,这些类映射到某些持久存储区,ORM 工具 (EF) 小心的持久性的详细信息。ORM 公开一种查询语言 (LINQ to Entities)、 事务性语义 (EF 中的 xxxContext 对象) 和基本的创建、 读取、 更新和删除 (CRUD) API 支持并发、 延缓加载和提取的计划。

因此必须在模型中,并且您知道如何将其保存在以及如何查询从它的信息。这是一种模型,您可以在您的应用程序中的场合使用吗?更具体地说,这是您可以有效地初表示层模型吗?这是具有在理论和实践明显的差异,一个真正 sore 点上下文是金永昌和不确定性 (如果不是这样的混淆) reigns。请允许我提供具体的示例绑定到流行的 ASP。NET MVC 技术。我使用 ASP 的唯一原因。NET MVC 代替说,Silverlight,是由 ASP。NET MVC 具有名称 (在 MVC 中的 M) 中的单词模型 — 和我已提出了次数过多类和会议中有关 ASP 中的"模型"的确切位置。NET MVC 应用程序。

今天,即使在后三个版本,asp 的太多教程。NET MVC 坚持使用查询、 更新和演示文稿的只是一个模型。许多教程还保留在主项目内的模型的定义。它的工作原理,所以其中的问题?问题不是使用解决方案,工作、 有效,且正是我经常使用过自己,并打算继续使用。实际上没有一套现实,但简单和相对短期的应用程序 (而不只是演示和教程),可以开发与简单模式。使用只有一个模型的问题在于它传输的教程主要使用者的消息: 打算学习一种技术的开发人员。只在一个位置有一个模型建议 (是否不建议这样做),它是首选的做事方式。是,而不仅仅是一种特殊情况 — — 一个非常简单而有利的方案。如果您将实际的工作中的实际应用场景相匹配,您就超过正常。否则,您是停滞且准备好为您第一个"大球形 mud 合并的"随增长而越来越大。

更多的常规体系结构

让我们首先使用稍微不同的名称。让我们调用模型所保持的域模型和呼叫数据的数据您管理视图中查看模型。我应提到的域模型不是完全中性术语在软件中,如它指向的对象模型旨在根据附加的规则数。在本文的范围中,我没有使用从 Domain-Driven 设计 (DDD) 方法体系的结果的含义。对于我来说,在这里,域模型已只是您保持的对象模型 —实体模型可能是另一个等效 — 和更少的让人眼花缭乱的 — 术语。

在后端应用程序 ; 在实体模型中使用类 表示层中的视图模型中使用类。请注意,但是,在 ASP。NET MVC 表示层是控制器。控制器应接收数据准备好的用户界面。中间层组件接收并返回查看模型对象并在内部使用实体对象。图 1 显示在典型的多层项目的依赖项的 web。

Connections Among Layers
图 1 层间的连接

演示文稿 (即,代码隐藏或控制器类) 引用的应用程序逻辑,即执行应用程序的使用案例的组件。应用程序逻辑从技术上讲属于业务层或层,并在非常简单的情况下可能会与合并演示文稿。这是发生在某些需要隔离在其自己的图层中的应用程序逻辑的感受太简单或设计不良的教程和演示文稿和数据访问层 (DAL) 之间的拆分应用程序逻辑。

应用程序逻辑程序集实现的服务层模式并将两个接口层分离: 演示文稿和数据。应用程序逻辑引用实体模型 (您的域类) 和 DAL。应用程序逻辑协调 DAL、 域类和服务,以争取拿下预期的行为。应用程序逻辑与通过查看模型对象的表示层通信,并与域对象通过 DAL 进行通信。DAL,反过来,引用的模型和 ORM 程序集。

在实体框架上的几个字

此体系结构中,假定为 ORM EF 看一下。EF 并不只是 ORM、 但顾名思义,它不会 ORM、 再加上提供一个框架,用于创建模型的典型工作。想法不错,但它不应该被遗忘我们正在跨越两个不同的图层 — 业务和 DAL。类是业务需要。 持久性引擎是 DAL。用于 EF,持久性引擎 (ORM 程序集) 是 system.data.entity 及其依赖项,包括 ObjectContext 类。说另一种方法,除非您使用 POCO 类和第一个代码,您将有可能得到 ORM 上具有依赖关系的域模型。域模型应使用 POCO — — 也就是说,除此之外,它应该是一个独立的程序集。有关此主题感兴趣的线程存在于堆栈溢出在 bit.ly/mUs6cv。有关如何拆分 EF 中的上下文中的实体的详细信息,请参阅 ADO。NET 小组网络日志项,"演练: 随着时间模板用于实体框架"(bit.ly/bDcUoN) 和"EF 4.1 模型 & 数据库第一个演练"(bit.ly/hufcWN)。

从这种分析,它看上去 POCO 属性是必需的域类。随着时间,当然,表示具有其自己的程序集之外的任何依赖项的类。POCO 是有关简单起见,永远不会有误。不会 POCO 方式意味着形式的图层之间的紧密耦合。紧密耦合不可 poisonous,并且不会立即终止您,但它可能需要慢速死亡的项目。签出我在上月的问题的软件灾难有关的专栏 (msdn.microsoft.com/magazine/hh394145)。

该模型是什么?

当您创建一个对象模型时,您创建一个类的库。您可以组织到多个模式,根据对象模型,但实际上它归结为面向表的方法和面向对象的方法之间进行选择。

您如何设计类?它们应具有哪些功能?特别是,您的类应注意数据库吗?它们应包括逻辑 (即,方法) 或被限制为只公开属性吗?有两个主模式,您可以参考: 活动记录和域模型。

在活动记录图案中,您的类是密切仿效数据库表。多数情况下有一个类,每个表和每个列的一个属性。更重要的是,类是负责他们自己的持久性和他们自己简单、 最小域逻辑。

以域模型模式中,根据您的类都被为了提供问题的域的概念性视图。这些类与数据库之间没有关系,并具有属性和方法。最后,这些类不会负责他们自己的持久性。如果您选择一种域模型的方法,委托给不同的图层具有持久性 — DAL。自己,编写这一层,但它不是很有趣吧。旨在根据域模型图案库的 well-done DAL 在 ORM 工具几乎相同。那么为什么不使用现有的 ORM 工具之一呢?

尤其是当您使用自动代码生成器,EF 获取所做具有只有属性的类的对象模型。所使用的图案当然不是活动的记录,但默认情况下,类具有任何方法。幸运的是,类被标记为分部的这样就使您可以通过添加通过分部类的逻辑更丰富的域模型创建形状。然后,如果您选择的第一个代码的方法,您完全负责从开始到完成写入您的类的源代码。

唯一的功能属性通常是对象模型中的类被称为贫乏的域模型。

存储库

正在赢得很高的受欢迎度较好的做法环绕表面类称为存储库中的数据访问代码。存储库组成一个接口和实现类。通常有一个存储库用于每个重大模型中的类。对象模型中的一个重要类是一个类来控制其自己的持久性,并且对自己的具体情况取决于域名,不会在其他类代表。一般情况下,例如,客户是一个重要的类,而明细无效,因为您将始终会使用订单详细信息,如果您有一个订单。DDD,在重大的类称为聚合的根。

若要提高设计,您可以建立应用程序逻辑和通过存储库接口 DAL 之间的依赖关系。然后可以根据应用程序逻辑中注入实际的存储库。图 2 显示生成的体系结构 DAL 所基于的存储库。

Using Repositories in the DAL
图 2 使用资料库中 DAL

存储库使 DAL 中的依赖项注入,因为您可以轻松地拔下提供持久性逻辑在当前模块并将其替换为您自己。这是对于可测试性,当然有益,但它并不局限于此。根据存储库体系结构允许欺 DAL 和隔离在测试应用程序逻辑。

存储库还表示您的应用程序的卓越扩展性点。通过替换存储库,您可以替换对图层的其余部分是透明的一种方法中的持久性引擎。这里的要点并不使很多有关切换,说,Oracle SQL Server,因为 ORM 工具已经提供这一级别的灵活性。这里的要点能够从 DAL 的当前实现切换到不同云 API、 动态 CRM、 NoSQL 解决方案以及其他类似的地方。

资料库应该不是什么

存储库是一部分 DAL; 在这种情况下,它不应该了解的有关应用程序逻辑。这可能是太显而易见的但我经常看到这些天根据演示文稿和资料库的体系结构关系图的类型。

如果您的实际逻辑是精简和简单 — 或者是本质上是 CRUD — 则此关系图是多个确定。但如果不是这样吗?如果是这样,您肯定需要的中间在哪里部署您的应用程序逻辑中的位置。并且,相信我,我曾看到过只有少数的应用程序都只是在我职业生涯中的 CRUD。但可能我只是不是 … 幸运手册

阐明隐匿性来实现

收尾,如今的应用程序往往围绕 ORM 工具然后仍然存在一些数据存储区的数据模型设计。这是相当不错的后端应用程序,但不会太惊讶,如果用户界面需要您能够处理明显不同的只是不存在原始模型中的数据聚合。必须创建用户界面的目的存在这些新数据类型。和它们最终会形成一个完全平行的对象模型: 查看模型。如果减少这两个建模只与一个,然后通过全部是严格遵守的并感到高兴。如果没有,但愿这篇文章澄清一些隐蔽点。

Dino Esposito是作者的"编程 Microsoft ASP。NET MVC3"(微软出版社,2011年) 和 coauthor 的"Microsoft。NET: 构建企业应用程序"(微软出版社,2008年)。Esposito 定居于意大利,经常在世界各地的业内活动中发表演讲。您可以按照他在 Twitter 上 twitter.com/despos

这要归功于以下的技术专家审阅这篇文章:Andrea Saltarello圣地亚哥 Vega