扩展 Visual Studio 的数据库功能

可以通过创建功能扩展来扩展 Visual Studio 高级专业版或 Visual Studio 旗舰版。 使用这些功能扩展,可以扩展 Visual Studio 高级专业版或 Visual Studio 旗舰版的功能,如重构、数据生成、单元测试和数据库代码分析。 由于您在创建功能扩展时使用的是基功能的现有框架,因此大大减少了您需要编写的代码量。

功能扩展具有定义完善的扩展点。 无需安装 Visual Studio SDK 即可为 Visual Studio 高级专业版或 Visual Studio 旗舰版创建功能扩展。

常规高级任务

高级任务

支持内容

了解数据库扩展中的概念:在扩展这些功能之前,您应了解扩展在 Visual Studio 高级专业版或 Visual Studio 旗舰版中的工作方式。 数据库架构提供程序实现了特定于数据库的特定品牌和版本(如 SQL Server 2008)的所有服务。 这包括用于读取和编写该数据库的脚本的分析器、表示脚本的脚本域对象模型(脚本 DOM)、用于为对象、关系和数据库对象的属性建立模型的架构模型。 在 Visual Studio 高级专业版或 Visual Studio 旗舰版中,只要您与某项功能或功能扩展进行交互,这些功能和功能扩展就会对 DSP 服务、脚本 DOM 和架构模型的某些组合进行操作。

  • 建立数据库模型

  • Database Edition 中的扩展组件

  • 功能扩展的类型

  • 数据库架构提供程序的核心组件

添加对新的数据库重构类型的支持:可以为数据库重构创建功能扩展以启用新的数据库重构类型。 此外,每个新的重构类型还需要一个或多个新的重构参与者。

添加对新的数据库重构目标的支持:可以使现有的数据库重构类型支持更新新的项目类型(例如文本文件),或支持从包含数据库信息的第三方应用程序进行输出。 如果创建了一个新的重构类型,则必须实现一个或多个重构参与者才能使该类型能够对数据库项目中包含的项目进行操作。

定义新的数据库代码分析规则:可以定义新的数据库代码分析规则,用于查找 Visual Studio 高级专业版或 Visual Studio 旗舰版附带的规则未检测到的问题。

创建自定义数据生成器:自定义数据生成器可用于生成不泄漏敏感信息的真实测试数据。 可以创建自定义数据生成器来补充 Visual Studio 高级专业版或 Visual Studio 旗舰版中包含的数据生成器。

添加自定义数据库单元测试条件:通过定义自定义测试条件,可以用内置单元测试条件不支持的方式验证数据库对象的行为。

自定义数据库项目行为:通过定义自定义数据库项目功能,可以用内置数据库项目不支持的方式修改项目行为。

建立数据库模型

为了建立数据库模型,Visual Studio 将对构成数据库的数据定义语言 (DDL) 的脚本和执行这些脚本时将生成的数据库进行建模。 DDL 脚本的模型由脚本 DOM 提供。 生成的数据库的模型由架构模型提供。

扩展组件之间的数据流

下图演示数据流经这些组件的方式。

扩展组件之间的数据流

扩展性组件之间的数据流

数据库对象的定义将以 DDL 脚本的形式保留在数据库项目中。 在打开数据库项目时,将读取这些脚本并填充两个模型:脚本 DOM 模型和架构模型。 Visual Studio 高级专业版的功能将与这两个模型进行交互,在保存对数据库对象所做的更改时,这些更改将保存回 DDL 脚本中。

Database Edition 中的扩展组件

下图演示了一些组件,通过对这些组件进行交互,您可以扩展 Database Edition 的功能。

扩展组件之间的通信

Database Edition 的扩展性组件

在打开或创建任何数据库项目时,扩展管理器组件会加载任何已注册的数据库架构提供程序。 在对某个数据库架构提供程序 (DSP) 使用特定功能时,扩展管理器组件会加载支持该 DSP 的功能及扩展。 例如,在使用重命名重构功能来重命名 SQL Server 2008 数据库中的对象时,会将重构功能与 SQL Server 2008 的重构类型和参与者一起加载。

扩展管理器

在运行 Visual Studio 高级专业版或 Visual Studio 旗舰版时,所有数据库项目、架构提供程序、功能和功能扩展都会与单一实例 ExtensionManager 进行交互。 扩展管理器会为每个数据库项目加载派生自 DatabaseSchemaProvider 的单一实例。 例如,当 Visual Studio 高级专业版或 Visual Studio 旗舰版打开一个 Microsoft SQL Server 2005 项目时,扩展管理器会加载 Sql90DatabaseSchemaProvider(派生自 DatabaseSchemaProvider)的一个实例。

扩展管理器将根据由这些扩展实现的接口的类型来加载扩展。 例如,在使用数据库单元测试功能时,扩展管理器将返回一个已注册扩展的列表,这些扩展继承 TestCondition 基类(其扩展与数据库项目的数据库架构提供程序兼容)。

功能扩展兼容性

一个功能(如重构或静态代码分析)是由特定于 DSP 的组件和支持所有 DSP 的组件(DSP 不可知的组件)构成的。 在定义一个功能扩展时,请用特定的 DSP 或基 DSP 声明该扩展的兼容性,以便只会为适当的项目类型加载该扩展。 例如,您可以声明您的扩展与 Sql90DatabaseSchemaProvider(仅适用于 SQL Server 2005 项目)或 SqlDatabaseSchemaProvider(SQL Server 2005 和 SQL Server 2008 DSP 的基类)兼容。 您也可以声明扩展将与多个特定的 DSP 兼容。 如果您无法确定将来版本是否会损坏您的功能,则可以使用此方法。 若要声明一个功能将与所有 DSP 兼容,请声明此功能与 DatabaseSchemaProvider 基类兼容。

示例

定义与一个 DSP 兼容的扩展:

// SqlSchemaObjectDesigners is defined as compatible with all Sql 
// database services providers.  
[DatabaseSchemaProviderCompatibility (typeof(Sql90DatabaseSchemaProvider))]
internal class SqlSchemaObjectDesigners : ISchemaObjectDesigners
{
}

定义与多个 DSP 兼容的扩展:

// Extension InconclusiveCondition is defined as compatible with all 
// SQL Server database services providers and Oracle database 
// services providers.
[DatabaseSchemaProviderCompatibility (typeof(SqlDatabaseSchemaProvider))]
[DatabaseSchemaProviderCompatibility (typeof(OracleDatabaseSchemaProvider))]
public sealed class InconclusiveCondition : TestCondition
{
}

定义与所有 DSP 兼容的扩展:

// Extension ReportingService is defined as compatible with all
// database services providers.
[DatabaseSchemaProviderCompatibility (typeof(DatabaseSchemaProvider))]
internal class ReportingService : IReportingService
{
}

定义与任何 DSP 都不兼容的扩展:

// Extension ExecutionTimeCondition is defined as compatible with no
// database services providers.  That means if a feature
// has an ExtensionManager constructed with null, it will load
// those extensions defined as binding to 
// DspCompatibilityCategory.None
[DatabaseSchemaProviderCompatibility (DspCompatibilityCategory.None)]
public sealed class ExecutionTimeCondition : TestCondition
{
}

功能扩展的类型

可以创建用于提高 Visual Studio 高级专业版或 Visual Studio 旗舰版的某些功能的能力的功能扩展。 下表介绍了可以创建的扩展的类型。

功能

扩展类型

说明

数据库单元测试

单元测试条件

可以添加自定义断言来确定测试是成功还是失败。 大多数用于单元测试的 API 都是公共的,但这种 API 并不表示扩展点。 这些 API 用于创建使用托管代码(如 Visual C# 或 Visual Basic)编写的数据库单元测试。 有关更多信息,请参见定义数据库单元测试的自定义条件

数据生成

数据生成器

如果数据生成器是 Visual Studio 高级专业版或 Visual Studio 旗舰版附带的,则可以使用扩展性 API 来创建自定义数据生成器。 有关更多信息,请参见用自定义数据生成器生成专用的测试数据

数据库代码分析

代码分析规则

可以定义您自己的代码分析规则,以检查数据库代码中的特定问题。 有关更多信息,请参见创建和注册用于分析数据库代码的其他规则

数据库重构

重构目标

可以扩展现有重构类型,以便对新目标(如新的文件类型)进行操作。 有关更多信息,请参见演练:扩展数据库重命名重构,对文本文件进行操作

数据库重构

重构类型

可以创建新的重构类型,如将嵌套的条件语句替换为临界子句。 有关更多信息,请参见创建自定义数据库重构类型或目标

数据库架构提供程序的核心组件

数据库架构提供程序 (DSP) 由三个组件组构成:

  • 脚本 DOM:一个对象模型和用于对包含 DDL 和 DML 语句的任意 SQL 脚本进行建模的支持服务。

  • 架构模型:一个对象模型和用于对数据库实例中的对象(如表、视图和存储过程)进行建模的支持服务。

  • 用户交互服务:一个服务集合,这些服务使核心组件能够访问用户界面资源,如表示对象名称的字符串、表示对象类型和类别的图标以及在其中显示这些对象的层次结构。

DSP 的主要用途是启用在脚本 DOM 和架构模型表示形式中处理 DDL 脚本的功能,并启用从两类模型表示形式重现脚本的反转功能。

脚本 DOM

脚本 DOM 不仅提供用于将一个 DDL 脚本分析成表示该脚本的对象模型的实现, 而且还提供用于从该模型重现原始脚本的实现。

下图演示数据流经脚本 DOM 的方式。

通过脚本 DOM 的数据流

通过脚本 DOM 的数据流

脚本 DOM 分析器会将存储在非结构化文本文件中的脚本转换为一个继承 IScriptFragment 接口的对象。 脚本 DOM 中的脚本生成器会采用一个继承 IScriptFragment 接口的对象并生成原始脚本。 在 SQL Server 的数据库架构提供程序(Visual Studio 高级专业版或 Visual Studio 旗舰版附带的)中,IScriptFragment 会提取一个抽象语法树 (AST) 和一个标记流。

标记提供了脚本的非结构化表示形式。 集合中的每个标记都具有:

  • 标记类型(如关键字或字符串文本)

  • 标记字符串

  • 标记所在的源文件

  • 标记所在的源文件内的偏移量

抽象语法树 (AST) 提供了脚本的结构化表示形式。 AST 中的每个节点均表示一批语句、一个语句或单个语句的一个组件(如一个表达式)。 AST 既可用于对解析后的脚本进行分析, 又可用于以编程方式生成脚本。

架构模型

架构模型表示形式是一个基于接口的对象模型,可用于对实时数据库实例进行建模。 接口在一个派生层次结构中进行排列,此结构包含一个由所有 DSP 共享的抽象层和任意数量的面向更具体的模型细节的抽象层。 例如,ISql90Table 接口继承 ISqlTable,而后者继承抽象层接口 IDatabaseTable。 架构模型采用 IScriptFragment 对象并将其转换成架构模型元素,此外还会执行反向转换(即将架构模型元素转换成 IScriptFragment 对象)。 架构模型由一些模型撰写器实现构成。 每个实现都会从系统中的其他一些资源创建一个模型。 例如,ScriptModelComposer 会从数据库项目中维护的脚本文件撰写模型。

架构模型基础结构(ModelStore 及其支持类)直接从模型元素实现集成的脚本 DOM 引用。 这将启用对包含任意脚本的对象(如存储过程)的建模。

架构模型包含一个由元素和批注构成的集合。 元素描述要对其进行建模的项目,如表、视图、存储过程、触发器和列等。 批注用于将任意数据与模型关联。 批注既可以由数据库项目核心组件使用,也可以由项目功能和功能扩展使用。 元素和批注既可以是命名的,也可以是匿名的。

模型元素

元素由属性和关系组成。 属性表示基本数据(如整数、布尔值和字符串),可用于捕获模型的详细信息。 关系表示元素之间的命名连接和类型化连接。 例如,ISqlTable 元素可维护名为“Columns”的 ISqlColumn 类型的关系,用于将表与表列相关联。

有三种基本类型的关系:

  • 对等 - 表示一个元素通过任意方式依赖于另一个元素。 在 SQL Server 中,最好是将视图和表之间的关系作为对等关系进行建模。

  • 组成 - 表示一个元素由其他元素组成。 在 SQL Server 中,最好是将表和其列之间的关系作为组成关系进行建模。 组成关系的主要原则是在一个操作中同时创建两个元素。 对于创建或移除,这些元素没有依赖顺序。 不过,模型将维护父级到子级的依赖方向以便启用关联依赖项。 例如,当一个列依赖于某个特定类型时,若父表依赖于其组成列,则意味着父表也依赖于该类型。

  • 层次 - 表示一个层次结构。 层次关系不同于组成关系,这是因为其依赖方向是从子级到父级(而不是相反方向)。 SQL Server 中的示例是一个架构和一个拥有的对象(如表或视图)之间的关系。 表与其架构一起参与层次关系。

下图演示可在架构模型中表示的三种不同类型的关系。

架构模型中的对象关系

架构模型中的对象关系

模型中的每个关系都会声明其自身是多重关系还是单一关系。 在所有情况中,一个元素都可以维护一个空白关系。 模型可以是实际项目的不完全模型。

元素是基于接口的,以便支持存储实现中的以下功能:

  • 强元素类型(标识)

  • 多重继承

    • 支持系统中的 DSP 不可知的部分和特定于 DSP 的部分

    • 支持不相关的元素类型之间的“质量”共享

  • 版本灵活性和扩展性

所有模型元素类都会实现公共 IModelElement 接口。 可以使用 ModelStore 元数据 API 从该类访问属性、关系和批注。 类似 IDatabaseTable 的接口可通过更简单且可维护性更好的方式,提供对属性和关系的访问(在编译时绑定)。

模型批注

与元素一样,批注也是由属性构成的。 但与元素不同的是,批注不参与关系。 相反,批注将附加到元素或模型存储区自身。 批注是强类型的,不仅可以将批注的单一实例附加到模型存储区,还可以将其附加到多个元素。 模型附加的批注表示模型的一个“全局”批注实例。