4

オンプレミスの SQL Server 2012 のデータベースを SQL Azure にコピーする継続的インテグレーション MSBuild スクリプトを作成しています。

簡単でしょ?

メソッド

かなりの調査の後、次の方法に出くわしました。

  1. PowerShell を使用して DAC ライブラリに直接アクセスし、 MSBuild PowerShell 拡張機能を使用してスクリプトをラップします。これには、PowerShell 3 をインストールし、MSBuild PowerShell 拡張機能をそれで動作させる方法を検討する必要があります。これは、MS がライブラリの最新バージョンで DAC API を別の名前空間に移動したようです。PowerShell は API への直接アクセスを提供しますが、かなりのボイラープレートが必要になる場合があります。

  2. サンプルの DAC Framework Client Side Tools を使用します。これには、自分でコンパイルする必要があります。Codeplex から入手できるダウンロードにはHosted バージョンのみが含まれているためです。また、現在は以前のバージョンの DAC を使用しているように見えるため、DAC 3.0 クラスを使用するように修正する必要があります。その後、これらのツールを<Exec Command="" />MSBuild スクリプトから呼び出すことができます。ボイラープレートが少なくなり、道にぶつかった場合でも、ソースに変更を加えることができます。

プロセス

どちらの方法を使用しても、プロセスは次のいずれかになります。

  1. オンプレミス SQL Server 2012 からローカル BACPAC へのエクスポート
  2. BACPAC をブログ ストレージにアップロードする
  3. Hosted DACを介して BACPAC を SQL Azure にインポートする

または:

  1. オンプレミス SQL Server 2012 からローカル BACPAC へのエクスポート
  2. クライアント DACを介して BACPAC を SQL Azure にインポートする

質問

上記のすべては、標準機能のように見えるものに対してかなりの労力を費やしているようです...だから、車輪の再発明を開始し、すべての人が見ることができるように結果を文書化する前に、私が見逃したことが本当に明らかなことはありますか?ここ?MS がリリースした、私がまだ発見していない事前作成済みのスクリプトはありますか?

SQL Server Management Studio 2012 の GUI には、まさに私がやろうとしていることを実行するコマンドがあります (ローカル データベースを右クリックし、[タスク] をクリックし、[データベースを SQL Azure に展開] をクリックします)。確かにGUIで数回クリックするだけなら、どこかのコマンドラインの単一のコマンドでなければなりません??

4

1 に答える 1

1

そこで、クライアント DACのみで PowerShell を使用することにしました (これは実際にはスクリプトに近いため) 。ここの例はとても役に立ちました。

MSBuild 拡張パックを使用すると、PowerShell ボイラープレートをラップするタスクを作成できます。

DAC 3.0 にアクセスするには、PowerShell 3 をインストールする必要があることに注意してください。これは、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>

これは、参照実装のコンソール アプリを呼び出す代わりに、ホストされた DACを使用するように簡単に修正できます。<Exec Command="" /><ImportBacpac />

改善点があれば教えてください!

于 2012-09-25T21:08:31.413 に答える