通过 Visual Studio 进行数据库持续集成






4.85/5 (14投票s)
提供了一个用于可预测地编译、提取和部署数据库项目的框架。
引言
数据库是当今几乎所有现代商业应用程序的关键组成部分,但通常情况下,行业却忽略了数据库开发工具的生产。现有的工具通常面向 DBA 而非开发人员,并且几乎所有工具都需要一定程度的手动干预。
本项目提供了一种机制,可以自动生成一种可预测、可重复且专业的方法,用于将 SQL 代码从开发环境发布到生产环境。虽然该代码不明确要求 Visual Studio 数据库版才能工作,但我强烈推荐使用它,因为它是第一个提供 SQL 代码实时语法检查的 IDE - 它可以验证代码的完整性、对象引用(例如,您是否刚刚更改了列名?),并提供静态代码分析来突出显示那些常常被遗忘的错误(以及更多... 我不明白为什么 Microsoft 没有包含我添加的许多功能)。
我已解决的一些问题包括:
- 可预测性:在大多数现有环境中,数据库对象的脚本编写是一个主要的手动过程。即使使用了 Visual Studio 数据库版的 Schema Compare 或 RedGate 软件提供的工具,大多数开发人员仍然发现他们必须手动编写存在性检查脚本(例如,删除过程、检查表是否存在、查询 sys.indexes 表)。但绝大多数情况下,这很容易出错 - 复制对象 A 的存在性检查脚本,然后删除对象 B。现在,存在性检查将自动包含在脚本中,部署也不会因为表已存在而失败。
- 安全性:在大型组织中,安全性的脚本编写常常是一个问题。我已将所有数据库级别的安全性抽象为数据库级别的角色(正如其应有的样子!),并将实际的用户权限和访问权限留给 DBA,他们理应拥有对系统的完全控制权,而不必担心开发人员意外将开发环境的权限注入代码。此外,对于那些开发大型数据库的开发人员来说,您不必手动为每个对象编写每个权限的脚本 - 我提供了一种在构建时生成此脚本的机制,因此如果您忘记为某个存储过程添加权限,那么在推出时系统也不会中断。
- 可重复性:DBA 也是人,在推出过程中也会出错。连接断开、断电、DBA 在远程会话中复制粘贴内容时被截断 - 任何情况都有可能发生。必须能够从上次中断的地方继续处理,而一个在创建/修改每个对象之前都进行存在性检查的可重复脚本就能提供这样的框架。
- 灵活性:我使用过的其他实用程序会生成一个大型脚本。我一直觉得这很不灵活,尤其是在处理影响多个数据库的部署时,或者(天哪,如果)数据库之间存在循环依赖时。部署脚本按类型(例如,过程、表等)分离,并且可以按您想要的任何方式进行排序执行,因为您可以在过程的任何点注入自定义脚本。
设置示例项目
这很简单。下载源代码,解压缩,然后打开“Example VSDB Project”文件夹中的 SampleDB.dbproj 文件。确保 SampleDB.targets 文件中的以下行指向一个有效的 SQL Server 实例。
- 第 45 行:SqlInstance=".\SQL2005"
- 第 69 行:SqlInstance = ".\SQL2005"
- 第 76 行:ExtractFromServer = ".\SQL2005"(只有当您需要从静态数据库提取引用数据时才需要更改此项;默认设置为关闭)
在 SampleDB.targets 文件以及 CustomDeployment\ScriptExecutorConfiguration.xml 文件中提供了详细的注释。
准备就绪后,在 SampleDB.dbproj 文件所在的文件夹中打开 Visual Studio 命令提示符,然后运行以下命令行语句以提取您的架构。
MSBuild SampleDB.dbproj /Target:TheExtract
如果您希望将数据库作为构建过程的一部分进行部署,请将目标更改为 /Target:DeployDatabase。请注意,示例项目是一个简单的示例,但其中涵盖了您将使用的绝大多数对象类型。
Targets 文件
targets 文件有效控制着构建过程。下面是对示例项目随附的 targets 文件进行的详细解释。
<?xml version="1.0" encoding="Windows-1252"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- An example of how to execute this from the command line would be:
MSBuild SampleDB.dbproj /target:DeployDatabase
Since DeployDatabase depends on SQLExtract, both tasks will be executed.
-->
<UsingTask TaskName="DeployDatabase" AssemblyFile="lib\SqlDeployment.Build.dll" />
<UsingTask TaskName="SQLExtract" AssemblyFile="lib\SqlDeployment.Build.dll" />
<UsingTask TaskName="SqlScriptExecutor" AssemblyFile="lib\SqlDeployment.Build.dll" />
<!--
You probably want to reference a common drop point on a build server,
instead of a path relative reference
-->
<!--
This item is an enumeration of all "custom" files in the build
from the dbpro project that should be included in the build output.
Note that to include multiple files, simply use a semi-colon delimiter.
The ScriptExecutorConfiguration.xml file is the config used by the
database deployment task - it is a serialized dictionary
that is sorted to execute in sequence.
-->
<ItemGroup>
<CustomDeployment
Include="$(MSBuildProjectDirectory)\Scripts\CustomDeployment\*.sql;
$(MSBuildProjectDirectory)\Scripts\CustomDeployment\
ScriptExecutorConfiguration.xml"
Exclude="*.sqlfile;*.sqlpermissions"
/>
<!--
This item is an enumeration of ALL project files in the
build from the dbpro project that should be included in the build
Note that *.sql includes files such as .sqlfile and .sqlpermissions,
so we exclude them if they exist.
-->
<SchemaScripts
Include="@(Build->'%(FullPath)')"
Exclude="*.sqlfile;*.sqlpermissions"
/>
</ItemGroup>
<!--
SqlScriptExecutor - execute any ddl against a target database.
This one is used to restore a target image prior to build execution
SqlInstance - required. The SQLInstance against which the scripts will be executed
SqlUsername - The sql username to use when connecting to the instance.
Leave blank to use windows authentication.
SqlPassword - The password to use with the build account
DatabaseName - required. The database name against which the scripts
will be executed
ConfigPath - required. The path where the config file for the
.sql scripts is to be found.
-->
<Target Name="RestoreDatabase">
<SqlScriptExecutor
SqlInstance=".\SQL2005"
SqlUsername = "BuildServiceUser"
SqlPassword = "BuildServicePassword"
DatabaseName="master"
ConfigPath="RestoreBuildScript\RestoreConfiguration.xml"
/>
</Target>
<!--
Database deployment - test a deployment against your daily refresh from production
SqlInstance - required. The SQLInstance to which the scripts will be deployed
DatabaseName - required. The database name to which the scripts will be deployed
SqlUsername - The sql username to use when connecting to the instance.
Leave blank to use windows authentication.
SqlPassword - The password to use with the build account
ConfigPath - required. The path where the config file for the
extracted .sql scripts is to be found.
OutputCompoundFile - indicates whether or not a single output file
should be generated
OutputCompoundFilePath - the path of the output file
PrependUsingDatabaseName - if a single output file is generated and
this is set to "1", a using statement will be
placed at the head of the output file,
using the name of the database against
which the deployment was performed
-->
<Target Name="DeployDatabase" DependsOnTargets="TheExtract">
<DeployDatabase
SqlInstance=".\SQL2005"
SqlUsername = "BuildServiceUser"
SqlPassword = "BuildServicePassword"
DatabaseName="SampleDB"
ConfigPath="Build\ScriptExecutorConfiguration.xml"
OutputCompoundFile="1"
OutputCompoundFilePath="Build\SampleDB.sql"
PrependUsingDatabaseName="1"
/>
</Target>
<!--
SQL Extract - predictably extracts .sql files from a dbproject
SqlInstance - required. The SQLInstance against which the scripts
will be tested to assist in determining dependencies
SqlUsername - The sql username to use when connecting to the instance.
Leave blank to use windows authentication.
SqlPassword - The password to use with the build account
ProjectGUID - required. The GUID of the db project.
Will be included in the test database build name.
BuildPath - required. The path where the output .sql files will be deployed.
SchemaScripts - required. The path (and files) for extraction
StaticFiles - required. The path where the custom files reside.
SplitDropToSeperateFile - required. Indicates whether or not multiple
"object typed" files are cresated. Currently only the value of
"1" is supported.
ExtractData - Indicates whether or not reference data should be extracted
from a source database
ExtractFromServer - The name of the server from which the source data
should be extracted
ExtractUsername - The sql username to use when connecting to the
instance for extracting reference data.
Leave blank to use windows authentication.
ExtractPassword - The password to use with the build account
ExtractFromDatabase - The name of the database from which the
source data should be extracted
ExtractTargetFile - The file where the extracted data should be saved
ExtractCommandsFile - The SQL Commands (spGenerateMerge) used for the extract
ScriptPermissions - Indicates whether or not to script permissions
for this database
PermissionsTemplate - The template - (a serialized "Permissions Map" class -
to be used for permission generation
PermissionsTargetFile - The target file where the scripted permissions
will be written
AlterIfExists - If deploying against a known baseline, this will load up
the provider defined in ExistenceCheckerProvider and
for StoredProcedures, Functions and Views will NOT
generate a drop statement, but will only generate an ALTER.
ExistenceCheckerProvider - The provider to use to check if an object exists.
Can use a file manifest
(AdamNachman.Build.SqlExtract.ManifestExistenceChecker,
AdamNachman.Build.SqlExtract) - a list of objects in a
single file, or can check the schema of an existing
database (AdamNachman.Build.SqlExtract.SchemaExistenceChecker,
AdamNachman.Build.SqlExtract).
If in file, the format is [schema].[objectname],
with one item per line
ExistenceCheckerConfiguration - The configuration
for the ExistenceCheckerProvider -
the ManifestExistenceChecker expects a file path,
the SchemaExistenceChecker a connection string.
If a connection string, ensure that the semi-colons
are replaced with %3B
TreatWarningsAsError - Indicates that warnings should be treated as errors
and fail the build process
ExtractAssemblies - An indicator that CLR assemblies should be extracted
ExtractAssembliesConfig - The configuration for the assemblies to be extracted
-->
<Target Name="TheExtract">
<SQLExtract
SqlInstance = ".\SQL2005"
SqlUsername = "BuildServiceUser"
SqlPassword = "BuildServicePassword"
ProjectGUID = "$(ProjectGuid)"
BuildPath = "Build"
SchemaScripts = "@(Build->'%(FullPath)')"
StaticFiles = "@(CustomDeployment)"
SplitDropToSeperateFile = "1"
ExtractData = "1"
ExtractFromServer = ".\SQL2005"
ExtractUsername = "BuildServiceUser"
ExtractPassword = "BuildServicePassword"
ExtractFromDatabase = "SampleDBSource"
ExtractTargetFile = "$(MSBuildProjectDirectory)
\Scripts\CustomDeployment\LoadReferenceData.sql"
ExtractCommandsFile = "$(MSBuildProjectDirectory)\ExtractCommands.txt"
ScriptPermissions = "1"
PermissionsTemplate = "$(MSBuildProjectDirectory)\PermissionsTemplate.xml"
PermissionsTargetFile = "$(MSBuildProjectDirectory)\Scripts\
CustomDeployment\RolePermissions.sql"
AlterIfExists = "0"
ExistenceCheckerProvider = "AdamNachman.Build.SqlExtract.SchemaExistenceChecker,
AdamNachman.Build.SqlExtract"
ExistenceCheckerConfiguration =
"Server=.\DEV2005%3BDatabase=mySourceDatabase%3BTrusted_Connection=yes%3B"
TreatWarningsAsError = "1"
ExtractAssemblies = "1"
ExtractAssembliesConfig = "$(MSBuildProjectDirectory)\ExtractAssemblies.xml"
/>
</Target>
</Project>
Targets 模型很灵活,您可以通过将 targets 更改为 MSBuild SampleDB.dbproj /Target:TheExtract,DeployDatabase 来一步完成提取和发布。我的 targets 模式是 /Target:Build,TheExtract,RestoreDatabase,DeployToRestoredImage,PublishToShared,Checkin,其中 DeployToRestoredImage
在已恢复的生产备份映像上执行新提取的脚本,PublishToShared
更新共享开发环境(这两者只是 DeployDatabase
的不同参数复制),而 Checkin
将脚本添加到源代码存储库。每一步仅在前一步成功后执行。
在您的项目中使用程序集
基本上,整个过程由 MSBuild targets 文件控制。对于不熟悉 MSBuild 过程的读者来说,您可以将 targets 文件视为一个类别的序列化存储库,该类别代表了一系列任务的配置和执行顺序。在我提供的示例项目中,我已经编辑了 .proj 文件以包含自定义 MSBuild 目标。
整个过程分为以下几个步骤:
- 代码提取(
TheExtract
) - 解析项目文件,在内存中为每个架构对象创建一个类。
- 创建一个本地测试数据库。
- 将 DLL 执行到本地数据库,检查依赖项以允许我们正确排序内容,从而消除部署时的警告。
- 将输出的 .sql 文件写入构建文件夹中的磁盘。
- 将静态文件(自定义部署文件)写入构建文件夹。
- 部署数据库(
DeployDatabase
) - 验证数据库连接。
- 读取并排序 ScriptExecutorConfiguration.xml。
- 按顺序执行脚本,从构建路径读取脚本。
请注意,我已决定在每次部署时始终删除并替换所有存储过程、视图(包括索引视图)和函数。这可以自动化重新编译,并确保使用最新版本的代码部署到生产环境。有些人可能会争辩说,这会带来风险,如果生产环境中的某个更改丢失,它将永远丢失。我的观点是,如果它一开始就不存在于项目的源代码存储库中,那么它就不存在,所以没有什么可失去的... :) 。
在持续集成环境中,理想情况下,Deploy Database 步骤的目标数据库应该是生产映像的每日刷新。这样,您将每天了解自己是否破坏了什么,并能在项目的早期解决它。显然,在企业环境中,备份 TB 级的大量实时数据是不切实际的 - 在这里,您需要依靠 DBA 的协助,提供足够的示例数据和正确的生产架构。此外,鉴于您的项目将存储在源代码存储库(TFS、Subversion 等)中,DBA 所做的任何即时生产更改都可以直接应用于项目文件。
发布您的数据库项目更新
添加新架构
假设新的架构对象可以在不修改现有对象的情况下添加(例如,添加新表或新存储过程),只需将新对象添加到数据库项目中,然后让提取过程处理其余的工作。只要该文件(例如,TableFive.table.sql)包含在项目中(并在文件属性中标记为 BUILD),它就会自动添加到提取的脚本文件中,并用存在性检查脚本进行包装。
更新架构
如果您想更新架构,有多种选项可供选择。您可以始终将自定义脚本添加到 CustomDeployment 文件夹,并在 ScriptExecutorConfiguration.xml 配置文件中添加新的序列项。但是,AlterTables.sql 文件包含在示例项目和默认 .xml 文件中,可以轻松用于扩展您的项目。假设您有一个表 TableOne
,并且想添加 Col5
。您将遵循以下步骤:
- 更改 TableOne.table.sql 中的
Create Table
语句,以包含新列。CREATE TABLE [dbo].[TableOne] ( [Col1] INT IDENTITY (1, 1) NOT NULL, [Col2] INT NOT NULL, [Col3] NVARCHAR (50) NOT NULL, [Col4] VARCHAR (50) NOT NULL, [Col5] INT NOT NULL );
这将确保新数据库包含此列。
- 为新列添加默认约束文件(新文件 DF_TableOne_Col5.defconst.sql)。
ALTER TABLE [dbo].[TableOne] ADD CONSTRAINT [DF_TableOne_Col5] DEFAULT ((0)) FOR [Col5];
当提取实用程序解析脚本时,它会自动为此约束创建存在性检查,因此脚本将是可重复的。
- 将检查列存在性的代码添加到 \Scripts\CustomDeployment\AlterTables.sql,如下所示:
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'TableOne') BEGIN IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA= 'dbo' AND TABLE_NAME='TableOne' AND COLUMN_NAME='Col5') BEGIN ALTER TABLE dbo.TableOne ADD [Col5] INT CONSTRAINT [DF_TableOne_Col5] DEFAULT (0) NOT NULL; END END GO
- 如果您查看源代码,有一个名为“
DatabaseDeployment
”的项目。这是一个简单的示例,展示了如何编写应用程序来处理生成的脚本文件并将其部署到目标数据库。这样,您就可以使用构建过程生成脚本,然后在客户那里执行它们。请注意,DeployDatabase
目标上还有一个OutputCompoundFile
标志。这指示自动部署任务生成一个按正确顺序附加的单个输出文件(如果您不想发送多个文件,可以将此文件部署给客户 - 我遇到过一些 DBA,他们只将更新作为单个脚本文件运行,并且除了 Management Studio 运行脚本外,不使用任何应用程序代码进行部署)。
从源数据库提取静态数据
在磁盘上的某个位置创建一个“源”数据库,并使用它来填充任何其他“默认”引用数据(查找表等)。将 ExtractData
标志更改为“1
”,确保 ExtractFromServer
和 ExtractFromDatabase
正确。
默认情况下,您已在 ExtractCommands.txt 文件中拥有从 TableOne
提取数据的正确命令。如果您想添加另一个引用表,只需添加另一行即可。请注意,“merge
”标志为 1 表示如果数据不存在则插入,如果已存在则更新。要仅处理插入,请将 @merge
设置为 0
。
新手(甚至中级和高级)用户应该不需要修改提取和部署代码以满足其需求。可能的例外情况是当存在代码未涵盖的新 DDL 类型时(或者我没有看到自己涵盖它的必要性)。总的来说,现有框架应该能满足 99% 的需求。
底线是,代码不会自动生成一套“增量”脚本,但由于其生成方式,如果您仔细编写 ALTER 语句,您就可以在新的和旧的客户机上使用相同的脚本,并且可以升级几乎任何以前版本的架构。脚本文件的默认排序(在 Scripts\CustomDeployment\ScriptExecutorConfiguration.xml 中配置)将确保正确执行升级。请注意,排序是开放式的,所以您可以随时插入自己的自定义脚本。只需确保 XML 中的项键是唯一的,并且位于您期望的排序位置(因为部署程序集会根据键号对它们进行排序,以防您将其插入到文件中的错误位置),您就可以根据需要进行扩展。
此项目明确不包括以下项:
- 文件。虽然文件组已得到处理,但物理文件被忽略。目前,我认为这是 DBA 的责任,而不是开发人员的责任,并且文件组将在没有物理文件的情况下创建。例外情况是新数据库上的主文件(即,Deploy 只在默认路径下创建一个新数据库)。这也适用于全文索引的文件。但是,没有什么能阻止您修改代码以允许这样做。
- SQL 2008 特定语法。虽然我确信绝大多数 SQL 源都可以解析,但我不敢说这是 2008 兼容的,因为我还没有用任何新类型(空间对象等)进行测试。但是,由于实际内容旨在由 Visual Studio 解析和编译,而我的代码仅对文件头应用正则表达式来确定类型,因此不太可能出现太大问题。
- 证书和加密密钥。同样,我认为这是 DBA 的职能(毕竟,他们总得做点什么,对吧?)。如果存在真正的需求,我很乐意根据需要扩展该系统。
- 用户定义类型和 XML 架构。.
我考虑过添加但从未做到的项目:
- 完成 SQL CLR 过程(如上所述)。
- 将输出编译成资源程序集而不是简单的文本文件,然后使用它来“构建版本”数据库。
我采用了敏捷的方法来开发这个库,虽然我不认为它已经完成(它会完成吗?),但我认为现在是将其公之于众并供其他开发人员使用的时候了。功能可以在需要时添加。
如果您遇到麻烦,请回复,我很乐意提供帮助。如果您想做出贡献,请这样做 - 这旨在造福整个社区。
如果我不使用 Visual Studio 怎么办?
有很多人不使用 Visual Studio,原因多种多样,从“不喜欢微软”到“使用免费开源产品”。这些都是有效的。必须指出的是,提取和部署实用程序不依赖于 Visual Studio,只有构建任务才依赖。这意味着您可以编写一个包装器,将所有相关参数传递给这些程序集(例如,为 CruiseControl.NET 创建一个自定义任务,或者只是一个传递指向磁盘上 .sql 文件的参数的可执行文件)。
为了协助您,我将解释现有程序集的结构(提供所有 C# 源代码)。
接口
一个包含跨项目常用接口的程序集。目前只有 ILogger
接口。
实用程序
一个包含 SerializableDictionary
的程序集 - ScriptExecutorConfiguration
类用于在人类可读/可编辑的 XML 格式的磁盘上存储 KeyCaluePairs
字典的基类。
SqlExtract
包含解析磁盘上 .sql 文件逻辑的程序集。这是生成 .sql 脚本的核心实用程序。
ScriptExecutor
执行 SQL 文件,并将 ScriptExecutorConfiguration.xml 文件作为输入的程序集。
构建
从 MSBuild 中调用的程序集。如果仔细查看构建任务的属性,您会发现它们继承自 MSBuild Task 类,例如:
public class SQLExtract : Microsoft.Build.Utilities.Task
属性直接映射到 XML 中任务的属性,例如:
public Microsoft.Build.Framework.ITaskItem ExtractData
构建任务只是包装了底层的 SQLExtract
和 ScriptExecutor
程序集,在调用 Execute
方法时将这些属性传递下去。因此,例如,如果您不使用 Visual Studio 并仅将自己的 .sql 文件存储在磁盘上,您可以编写一些代码直接调用 SQLExtract
类,自己设置所有 public
属性,并将 .sql 文件的 List<string>
传递给它。或者,一个执行相同操作的 CruiseControl.NET 任务。或者,您可以直接从 TeamCity 或 TFS Build 或命令行调用现有的 MSBuild targets - 一切都取决于您。
DatabaseDeployment
如前所述,这是一个示例应用程序,按顺序执行磁盘上的脚本文件。您可以使用它来在生产环境中部署数据库。最适合那些 SQL 技能很少或没有的客户,您可以控制部署由您自己的应用程序完成。
支持的数据库对象
- 表格
- 视图
- 索引视图
- 函数
- 文件组
- 约束
- 索引(聚集和非聚集)
- Service Broker 队列
- 合同
- 消息
- 服务
- 路由
- 全文目录
- 全文索引
- 分区函数
- 分区方案
- 存储过程
- 数据库角色
- 架构
- 触发器
- Assemblies
- 可能还有我无意中包含的其他内容... 如果您有任何具体要求,请随时告诉我。
为记录在案,我目前正在将此应用于二十多个不同的数据库项目,涵盖多个服务器,数据库大小从几百 MB 到 5 TB 以上不等,所有这些都集成到一个运行 Jetbrains TeamCity 的构建服务器中。这里的关键是一致性。通过可预测且可靠的构建过程,即时(或近即时)的故障通知,以及生产 DBA 在设计阶段的参与以最小化风险并促进沟通,我们在一个高度动态的 OLTP 环境中,面对一个非常不宽容的用户群体,成功地一次又一次地推出了更改。
历史
版本 1.3
- 添加了对分区方案和函数的支持。
- 为 ScriptExecutor 添加了新的包装器,允许单独的任务选项(示例用于恢复数据库基线)。
- 添加了在提取时检查现有架构(从文件或数据库)的支持,并为函数、存储过程和视图生成
ALTER
语句。
注意:这是在现有模型之后添加的,虽然有效,但在 24/7 环境中却失败了。这是因为在脚本结束时删除和重新创建对象以及分配权限会导致不支持每秒数千条消息且不可能有重大停机时间的情况下出现错误。创建ALTER
语句可以实现更具针对性的部署。要从头开始重新生成,只需将此配置选项的值设置为“0
”。 - 添加了对 SQL 身份验证和 Windows 身份验证的支持。
- 修正了
spGenerateMergeData
过程中数据长度大于 8000 个字符在提取时被截断的 bug。 - 修正了提取过程中生成的引用文件在重新生成之前被复制到目标输出文件夹的 bug。
版本 1.4
- 修正了提取次要架构索引时的错误。
- 添加了将警告视为错误的选项,这允许在缺少引用时构建失败。
- 应要求,将架构作为选项添加到权限映射类中,允许使用权限生成器定位特定架构。
- 迁移到 VS 2010。
- 扩展了示例提取命令,以展示更复杂的提取命令的使用。
- 注意:使用 VS 2010 时,Microsoft 的内部编译器现在可以捕获大多数关于缺少变量的问题(包括在区分大小写的排序规则下正确失败)。我知道的两个遗留问题包括未能检测到对表变量列的不正确引用,以及一个向需要 n 个参数的存储过程传递 n-1 个参数的调用被错误地解析(即,它成功了,而它应该失败)。
版本 1.5
- 应要求,我添加了支持从程序集提取位流并更新程序集 SQL 文件。这允许您引用外部程序集并自动提取源并更新您的项目文件(以及后续部署)。
注意:我不自动处理对程序集的任何依赖关系,也不自动创建任何函数或过程,并且我也不自动生成 ALTER 语句。这是因为我不想费力地检查程序集的接口以确保它向后兼容,从而使 SQL 安全地重新绑定 - 这应该在测试中发现。如果您有一个更新的程序集,我建议您自己在一个“预执行”脚本中显式处理对依赖函数/过程/约束的删除。您可以简单地创建自己的自定义脚本,将其添加到 ScriptExecutor 配置文件中,并为其分配一个较低的序列号,以强制其在其他语句之前执行。 - 添加了一个示例表值函数,该函数使用 SqlClr 来解析逗号分隔的整数列表并生成表变量。该函数包装在一个名为
GetIds
的 T-SQL 函数中,可用于高效地解析分隔的输入列表,并允许您在存储过程中将其连接起来。与任何 T-SQL 解析实现相比,在 CPU 利用率和内存方面,它的性能都更好。请注意,我甚至没有尝试优化它 - 有比这更快的。这只是一个高效使用 CLR 来执行 T-SQL 可以执行但执行效果不佳的任务的简单示例。 - 应要求,向 deploy 目标添加了一个选项,用于在复合输出文件前加上 using 语句,特别是为了照顾那些忘记在执行前选择正确数据库的 DBA...*唉*
- 向解析器添加了 70 多个单元测试,以防止发生像上次更新那样导致中断性的更改。
- 提高了解析器的整体性能(仍然使用正则表达式而不是词法分析器,但由于它目前工作良好,因此没有理由更改)。
- 编译为 .NET 4.0。
- 修正了提取脚本中导致排除列列表被忽略的 bug。
- 构建 1.5.3963
- 修正了在从构建源提取时存在性检查器中引入的 bug。
- 修正了在部署阶段执行时出现的 bug。
- 修正了在预置到单个文件提取时使用“
use
”语句。 - 添加了 Visual Studio 模板 - 只需将模板 zip 文件复制(不要解压缩)到 我的文档\Visual Studio 2010\Templates\ProjectTemplates。
关注点
令我惊讶的是,有多少专业人士似乎对 Visual Studio 的数据库版浑然不知。此外,由于微软(追溯性地)将其免费包含在 Developer Edition 中(因为它已包含在 VS 2010 中),因此成本不再是许多知情人士的障碍,但又不需要额外花费。只需在 Developer 版本之上安装 SP1,然后安装 Microsoft 的 GDR2 即可。