24

如何使用 Visual Studio 数据库项目使用静态的、源代码控制的数据填充数据库?我已经尝试了以下所有三种策略,发现每一种都比上一种更好。我正在使用但对策略 3 不完全满意。您还有其他选择吗?

  1. 将插入脚本放在“数据生成计划”文件夹中。引用“Script.PostDeployment.sql”文件中的脚本以将它们包含在部署过程中。

    -- 优点:直截了当
    -- 缺点:slooooooow
    -- 缺点:后续部署必须先删除静态数据或检查数据不存在 => 效率低下

  2. 第一次使用最方便的方法将数据插入数据库(例如,可以是 SSMS 编辑表功能)。使用 bcp 命令行实用程序提取该数据以创建一堆数据文件并将它们添加到您的项目中。创建在“Scripts.PostDeployment.sql”文件中引用的脚本,该脚本为每个数据文件执行“批量插入”语句。

    -- 优点:比插入语句快得多
    -- 优点:可以利用 SSMS 编辑表功能
    -- 缺点:每个批量插入语句都需要数据文件的完全限定文件名,所以如果数据文件位于我的机器上的“C :\Projects\Dev\Source\foo.dat" 那么远程开发机器也必须在该位置拥有它们,否则批量插入语句将失败
    - 缺点:在后续部署中执行批量插入语句之前必须删除现有静态数据

  3. 在部署过程中创建临时表来保存静态数据,并使用 sql merge 语句将这些表与目标表同步。请参阅这些博客文章中的任何一篇。

    -- 优点:似乎 sql 合并对问题有完美的语义
    -- 缺点:该策略的逻辑在每个文件中重复 -- 缺点:表定义在 sql 合并文件中作为临时表重复

有没有更好的替代策略?我放弃了策略 1,因为它太慢了。由于完全限定的文件名问题,我不喜欢策略 2。我对策略 3 感到满意,但并不激动。有最佳实践吗?

4

4 回答 4

8

在您的 insert.sql 脚本中,您可以在 [__RefactorLog] 表(部署使用的系统表)中放置一个 GUID,并在插入数据之前检查此 GUID 是否存在,如下所示:

:setvar SOMEID "784B2FC9-2B1E-5798-8478-24EE856E62AE" //在 VS2010 中使用 Tools\CreateGuid 创建 guid

如果不存在(从 [dbo].[__RefactorLog] 中选择 [OperationKey],其中 [OperationKey] = '$(SOMEID)')

开始

...

插入 [dbo].[__RefactorLog] ([OperationKey] ) 值('$(SOMEID)')

结尾

然后,只有在不存在或需要时才插入数据(通过更改 Guid)。

于 2011-03-08T14:16:40.223 回答
2

这就是我解决这个问题的方法,以防其他人发现这很有用......

策略是在构建数据库项目之前设置一个 sqlcmdvars 变量。此变量将包含可以从部署后脚本引用的构建文件夹的绝对路径。然后,在部署脚本中将它用于您可能需要的任何其他文件或资源将是一件简单的事情。这种策略的优点是所有路径都是相对于项目文件的,而不需要硬编码的共享路径。

创建一个新的 Sql 命令变量名称 $(MSBuildProjectDirectory)。这将在预构建脚本中被覆盖。

创建一个将设置 sql 命令变量并构建数据库的 msbuild 脚本。

<Project ToolsVersion="4.0" DefaultTargets="BuildDatabase"  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
<PropertyGroup>
    <DatabaseServer>(Local)</DatabaseServer>
    <DeploymentConnectionString>Data Source=$(DatabaseServer)%3BIntegrated Security=True%3BPooling=False</DeploymentConnectionString>
    <Configuration>Release</Configuration>
</PropertyGroup>
<Target Name="BuildDatabase">
    <!-- Sets the projet path variable so that the post deployment script can determine the location of the bulk insert csv files. -->
    <XmlUpdate
        Prefix="urn"
        Namespace="urn:Microsoft.VisualStudio.Data.Schema.Package.SqlCmdVars"
        XmlFileName="$(MSBuildProjectDirectory)\DatabaseProjectName\Properties\Database.sqlcmdvars"
        XPath="/urn:SqlCommandVariables/urn:Properties/urn:Property[urn:PropertyName='MSBuildProjectDirectory']/urn:PropertyValue"
        Value="$(MSBuildProjectDirectory)\DatabaseProjectName" />

    <MSBuild
            Projects="DatabaseProjectName\DatabaseProjectName.dbproj"
            Properties="Configuration=$(Configuration);
                    TargetDatabase=DatabaseName;
                    TargetConnectionString=$(DeploymentConnectionString);
                    GenerateDropsIfNotInProject=True;
                    BlockIncrementalDeploymentIfDataLoss=False;
                    DeployToDatabase=True;
                    IgnorePermissions=True"
            Targets="Build;Deploy">
        <Output TaskParameter="TargetOutputs" ItemName="SqlFiles"/>
    </MSBuild>
</Target>

如下更新您的部署后脚本...

BULK INSERT [dbo].[TableName] FROM '$(MSBuildProjectDirectory)\Scripts\Post-Deployment\Data\YourDataFile.csv'
WITH (FIELDTERMINATOR = ',', ROWTERMINATOR='\n')
于 2013-11-29T20:03:06.930 回答
1

您可以使用数据库项目的模式输出来更新目标数据库有一个cmd工具可以在其他机器上运行它在您的vs2010 IDE中没有

所以你的数据仍然是一样的,除非你在任何一列都有下降

于 2011-05-05T02:08:37.797 回答
0

我们尚未将 VS 2010 db 项目投入生产,但对于我们的内部项目,我们将生产数据库加载到目标数据库并在开发/测试阶段构建/部署到它。也就是说,我知道如果您有多个 prod 数据库和发送到每个数据库的静态数据,Tim 可能对您不起作用。但是,它可以用于像我们这样的单一产品数据库商店。

于 2011-02-28T20:36:32.073 回答