Msbuild 通过BACPAC将SQL Server 2012数据库复制到SQL Azure(用于持续集成)

Msbuild 通过BACPAC将SQL Server 2012数据库复制到SQL Azure(用于持续集成),msbuild,azure-sql-database,sql-server-2012,dac,bacpac,Msbuild,Azure Sql Database,Sql Server 2012,Dac,Bacpac,我正在创建一个持续集成MSBuild脚本,该脚本将本地SQL Server 2012中的数据库复制到SQL Azure 简单,对吗 方法 经过一番研究,我发现了以下方法: ,然后使用。这将需要安装PowerShell 3,并研究如何使MSBuild PowerShell扩展与它一起工作,以及如何在库的最新版本中使用不同的命名空间。PowerShell将提供对API的直接访问,但可能需要相当多的样板文件 ,这需要自己编译它们,因为Codeplex提供的下载仅包括。它还需要修复它们以使用DAC 3.

我正在创建一个持续集成MSBuild脚本,该脚本将本地SQL Server 2012中的数据库复制到SQL Azure

简单,对吗

方法

经过一番研究,我发现了以下方法:

  • ,然后使用。这将需要安装PowerShell 3,并研究如何使MSBuild PowerShell扩展与它一起工作,以及如何在库的最新版本中使用不同的命名空间。PowerShell将提供对API的直接访问,但可能需要相当多的样板文件

  • ,这需要自己编译它们,因为Codeplex提供的下载仅包括。它还需要修复它们以使用DAC 3.0类,因为它们目前似乎使用的是早期版本的DAC。然后,我可以从MSBuild脚本中的
    调用这些工具。少一些样板,如果我在路上遇到任何颠簸,我就可以对源代码进行更改

  • 过程

    无论采用哪种方法,该过程都可以是:

  • 从本地SQL Server 2012导出到本地BACPAC
  • 将BACPAC上载到博客存储
  • 通过将BACPAC导入SQL Azure
  • 或:

  • 从本地SQL Server 2012导出到本地BACPAC
  • 通过将BACPAC导入SQL Azure
  • 问题

    所有这些似乎都是相当多的努力,似乎是一个标准的功能。。。因此,在我开始重新发明轮子并记录结果以供所有人看到之前,我是否真的错过了一些明显的东西?微软发布的预写脚本中有我还没有发现的吗


    SQLServerManagementStudio 2012的GUI中有一个命令,它正是我想要做的(右键单击本地数据库,单击“任务”,单击“将数据库部署到SQLAzure”)。当然,如果只需在GUI中单击几下,它一定是某个地方的命令行上的一个命令???

    因此我决定使用PowerShell(因为这实际上更像是一个脚本),只需一个脚本。这个例子非常有用

    使用允许创建任务来包装PowerShell样板文件

    请注意,您必须安装PowerShell 3才能访问DAC 3.0,这最好通过安装Windows Management Framework 3.0来实现

    TaskFactory包装器如下所示:

    <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    
      <!-- This custom task encapsulates DAC Framework 3.0 BACPAC import and export routines,
           which are compatible with SQL Server 2012 and later, and SQL Azure -->
    
      <!-- Required Import to use MSBuild Extension Pack -->
      <PropertyGroup>
        <AssemblyFile>$(MSBuildExtensionsPath)\ExtensionPack\4.0\MSBuild.ExtensionPack.TaskFactory.PowerShell.dll</AssemblyFile>
        <SqlServerDacDll>C:\Program Files (x86)\Microsoft SQL Server\110\DAC\bin\Microsoft.SqlServer.Dac.dll</SqlServerDacDll>
      </PropertyGroup>
    
      <UsingTask TaskFactory="PowershellTaskFactory" TaskName="ExportBacpac" AssemblyFile="$(AssemblyFile)">
        <ParameterGroup>
          <ConnectionString Required="true" ParameterType="System.String" />
          <BacpacFile Required="true" ParameterType="System.String" /> 
          <DatabaseName Required="true" ParameterType="System.String" />
        </ParameterGroup>
        <Task>
          <![CDATA[
                #write progress to activity log
                $log.LogMessage([Microsoft.Build.Framework.MessageImportance]"High","Starting export of database '$databasename' to '$bacpacfile' with connection string '$connectionstring' ")
    
                # load in DAC DLL (requires config file to support .NET 4.0)
                # change file location for a 32-bit OS
                add-type -path "$(SqlServerDacDll)"
    
                # make DacServices object, needs a connection string
                $d = new-object Microsoft.SqlServer.Dac.DacServices $connectionstring
    
                # register events, if you want 'em
                register-objectevent -in $d -eventname Message -source "msg" -action { $log.LogMessage([Microsoft.Build.Framework.MessageImportance]"High", $Event.SourceArgs[1].Message.Message) }
    
                # Export schema and data from database $databasename
                $d.exportbacpac($bacpacfile, $databasename)
    
                # clean up event
                unregister-event -source "msg"
    
                $log.LogMessage([Microsoft.Build.Framework.MessageImportance]"High","Completed export of database '$databasename' to '$bacpacfile'")
          ]]>
        </Task>
      </UsingTask>
    
      <UsingTask TaskFactory="PowershellTaskFactory" TaskName="ImportBacpac" AssemblyFile="$(AssemblyFile)">
        <ParameterGroup>
          <ConnectionString Required="true" ParameterType="System.String" />
          <BacpacFile Required="true" ParameterType="System.String" /> 
          <DatabaseName Required="true" ParameterType="System.String" /><!-- Not relevant for Azure import, which uses the Bacpac file name as the database name -->
        </ParameterGroup>
        <Task>
          <![CDATA[
                #write progress to activity log
                $log.LogMessage([Microsoft.Build.Framework.MessageImportance]"High","Starting import of database '$databasename' from '$bacpacfile' with connection string '$connectionstring' ")
    
                # load in DAC DLL (requires config file to support .NET 4.0)
                # change file location for a 32-bit OS
                add-type -path "$(SqlServerDacDll)"
    
                # make DacServices object, needs a connection string
                $d = new-object Microsoft.SqlServer.Dac.DacServices $connectionstring
    
                # register events, if you want 'em
                register-objectevent -in $d -eventname Message -source "msg" -action { $log.LogMessage([Microsoft.Build.Framework.MessageImportance]"High", $Event.SourceArgs[1].Message.Message) }
    
                # Load bacpac from file & import to database named $databasename
                $bp = [Microsoft.SqlServer.Dac.BacPackage]::Load($bacpacfile)
                $d.importbacpac($bp, $databasename)
    
                # clean up event
                unregister-event -source "msg"
    
                $log.LogMessage([Microsoft.Build.Framework.MessageImportance]"High","Completed import of database '$databasename' from '$bacpacfile'")
          ]]>
        </Task>
      </UsingTask>
    
    </Project>
    
    <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <Import Project="BacpacImportExport.xml"/>
    
      <PropertyGroup>
        <TempBacpacFile>$(ReleaseFolderPublish)\$(DestinationDBName).bacpac</TempBacpacFile>
      </PropertyGroup>
    
      <Target Name="CopyAndReplaceDatabaseViaBacpac">
        <Message Text="Clean bacpac directory"/>
        <Exec Command="mkdir $(ReleaseFolderPublish)\" IgnoreExitCode="true"></Exec>
        <Exec Command="del /Q $(ReleaseFolderPublish)\*.bacpac " IgnoreExitCode="true"></Exec>
    
        <MSBuild Projects="$(MSBuildProjectFile)" Targets="ReportBuildProgress" Properties="Message=Exporting database to BACPAC from source"/>
        <ExportBacpac
          ConnectionString="$(SourceConnectionString)"
          BacpacFile="$(TempBacpacFile)"
          DatabaseName="$(SourceDBName)"
        />
    
    
        <MSBuild Projects="$(MSBuildProjectFile)" Targets="ReportBuildProgress" Properties="Message=Dropping database from destination (does not fail on error)"/>
        <MSBuild.ExtensionPack.SqlServer.SqlCmd TaskAction="Execute" Server="$(DestinationDBServer)" Database="master"
                                                LogOn="$(DestinationDBUser)" Password="$(DestinationDBPass)"
                                                CommandLineQuery="DROP DATABASE [$(DestinationDBName)];"
                                                RedirectStandardError="true" SeverityLevel="1" />
    
    
        <MSBuild Projects="$(MSBuildProjectFile)" Targets="ReportBuildProgress" Properties="Message=Importing database from BACPAC to destination"/>
        <ImportBacpac
          ConnectionString="$(DestinationConnectionString)"
          BacpacFile="$(TempBacpacFile)"
          DatabaseName="$(DestinationDBName)"
        />
    
      </Target>
    </Project>
    
    
    通过
    调用参考实现,而不是调用

    如果您发现任何改进,请告诉我