テスト環境にデータベース ロール メンバーシップを配置する

作成者: Jason Lee

このトピックでは、テスト環境へのソリューション デプロイの一環として、データベース ロールにユーザー アカウントを追加する方法について説明します。

データベース プロジェクトを含むソリューションをステージングまたは運用環境にデプロイする場合、通常、開発者にはデータベース ロールへのユーザー アカウントの追加を自動化させたくありません。 ほとんどの場合、開発者はどのユーザー アカウントをどのデータベース ロールに追加する必要があるかを理解しておらず、これらの要件はいつでも変化する可能性があります。 しかし、データベース プロジェクトを含むソリューションを開発またはテスト環境にデプロイする場合、以下に示すように通常は状況が異なります。

  • 開発者は通常、定期的に (多くの場合は 1 日に数回) ソリューションを再デプロイします。
  • データベースは通常、デプロイごとに再作成されます。これは、デプロイのたびにデータベース ユーザーを作成してロールに追加する必要があることを意味します。
  • 開発者は通常、ターゲットの開発またはテスト環境を完全に制御できます。

このシナリオでは、多くの場合、デプロイ プロセスの一環として自動的にデータベース ユーザーを作成し、データベース ロール メンバーシップを割り当てることが有益です。

重要な点は、この操作は特定のターゲット環境を条件とするものでなければいけないということです。 ステージングまたは運用環境にデプロイする場合は、この操作をスキップする必要があります。 開発またはテスト環境にデプロイする場合は、追加の介入なしでロール メンバーシップをデプロイする必要があります。 このトピックでは、この課題に対処するために使用できるアプローチの 1 つについて説明します。

このトピックは、Fabrikam, Inc. という架空の会社のエンタープライズ配置要件を題材にしたチュートリアル シリーズの一部です。このシリーズでは、サンプル ソリューション (Contact Manager ソリューション) を使用して、現実的なレベルの複雑さを持った、ASP.NET MVC 3 アプリケーション、Windows Communication Foundation (WCF) サービス、データベース プロジェクトなどを含んだ Web アプリケーションを取り上げます。

これらのチュートリアルの核心である配置方法は、「プロジェクト ファイルについて」で説明した分割プロジェクト ファイルのアプローチを基にして、ビルド プロセスを 2 つのプロジェクト ファイル (すべての配置先環境に適用されるビルド命令を含んだファイルと、環境に特化したビルド設定や配置設定を含んだファイル) で制御するものになっています。 ビルド時には、環境に特化したプロジェクト ファイルが環境に依存しないプロジェクト ファイルにマージされ、ビルド命令の完全なセットが形成されます。

タスクの概要

このトピックは次のことを前提としています。

テスト環境にデータベース プロジェクトをデプロイする場合に、データベース ユーザーを作成しロール メンバーシップを割り当てるには、以下を行う必要があります。

  • 必要なデータベース変更を行う Transact Structured Query Language (Transact-SQL) スクリプトを作成する。
  • sqlcmd.exe ユーティリティを使用して SQL スクリプトを実行する Microsoft Build Engine (MSBuild) ターゲットを作成する。
  • テスト環境にソリューションをデプロイする場合にターゲットを呼び出すようにプロジェクト ファイルを構成する。

このトピックでは、これらの各手順を実行する方法について説明します。

データベース ロール メンバーシップのスクリプト作成

Transact-SQL スクリプトは、さまざまな方法で、任意の場所に作成できます。 最も簡単な方法は、Visual Studio 2010 でソリューション内にスクリプトを作成することです。

SQL スクリプトを作成するには

  1. [ソリューション エクスプローラー] ウィンドウで、データベース プロジェクト ノードを展開します。

  2. Scripts フォルダーを右クリックし、[追加] をポイントしてから [新しいフォルダー] をクリックします。

  3. フォルダー名として「Test」と入力した後、Enter キーを押します。

  4. Test フォルダーを右クリックし、[追加] をポイントしてから [スクリプト] をクリックします。

  5. [新しい項目の追加] ダイアログ ボックスで、スクリプトにわかりやすい名前 (たとえば、AddRoleMemberships.sql など) を付けた後、[追加] をクリックします。

    In the Add New Item dialog box, give your script a meaningful name (for example, AddRoleMemberships.sql), and then click Add.

  6. AddRoleMemberships.sql ファイルに、以下を実行する Transact-SQL ステートメントを追加します。

    1. データベースにアクセスする SQL Server ログイン用のデータベース ユーザーを作成する。
    2. そのデータベース ユーザーを必要なデータベース ロールに追加する。
  7. ファイルは次のようなものになるはずです。

    USE $(DatabaseName)
    GO
    CREATE USER [FABRIKAM\TESTWEB1$] FOR LOGIN[FABRIKAM\TESTWEB1$]
    GO
    USE [ContactManager]
    GO
    EXEC sp_addrolemember N'db_datareader', N'FABRIKAM\TESTWEB1$'
    GO
    USE [ContactManager]
    GO
    EXEC sp_addrolemember N'db_datawriter', N'FABRIKAM\TESTWEB1$'
    GO
    
  8. ファイルを保存します。

ターゲット データベースでのスクリプトの実行

必要な Transact-SQL スクリプトはすべて、データベース プロジェクトをデプロイするときの配置後スクリプトの一部として実行するのが理想的です。 しかし、配置後スクリプトでは、特定のソリューション構成やビルド プロパティを条件としてロジックを実行することはできません。 代替策は、sqlcmd.exe コマンドを実行する Target 要素を作成することで、MSBuild プロジェクト ファイルから直接 SQL スクリプトを実行することです。 次のコマンドを使用すると、ターゲット データベースでスクリプトを実行できます。

sqlcmd.exe –S [Database server] –d [Database name] –i [SQL script]

Note

sqlcmd コマンドライン オプションの詳細については、「sqlcmd ユーティリティ」を参照してください。

このコマンドを MSBuild ターゲットに埋め込む前に、以下のように、どのような条件下でこのスクリプトを実行したいのかを検討する必要があります。

  • ターゲット データベースは、ロール メンバーシップを変更する前に存在している必要があります。 そのため、このスクリプトはデータベース デプロイの "後に" 実行する必要があります。
  • このスクリプトがテスト環境でのみ実行されるように条件を含める必要があります。
  • "what if" デプロイを実行している (つまり、デプロイ スクリプトは生成していても実際にはそれらを実行していない) 場合、SQL スクリプトを実行してはいけません。

プロジェクト ファイルの理解」で説明されている分割プロジェクト ファイルのアプローチを使用している場合、Contact Manager サンプル ソリューションで示されているように、SQL スクリプトに対するビルド指示を以下のように分割できます。

  • 必要な環境固有のプロパティはすべて、アクセス許可をデプロイするかどうかを決定するプロパティと共に、環境固有のプロジェクト ファイル (たとえば、Env-Dev.proj) 内に配置する必要があります。
  • MSBuild ターゲット自体は、配置先環境によって変化しないすべてのプロパティと共に、ユニバーサル プロジェクト ファイル (たとえば、Publish.proj) 内に配置する必要があります。

環境固有のプロジェクト ファイルでは、データベース サーバー名、ターゲット データベース名、およびユーザーがロール メンバーシップをデプロイするかどうかを指定できるようにするブール値プロパティを定義する必要があります。

<PropertyGroup>
   <CmTargetDatabase Condition=" '$(CmTargetDatabase)'=='' ">
      ContactManager
   </CmTargetDatabase>
   <DatabaseServer Condition=" '$(DatabaseServer)'=='' ">
      TESTDB1
   </DatabaseServer>
   <DeployTestDBRoleMemberships Condition="'$(DeployTestDBRoleMemberships)'==''">
      true
   </DeployTestDBRoleMemberships>
</PropertyGroup>

ユニバーサル プロジェクト ファイルでは、sqlcmd 実行可能ファイルの場所と、実行したい SQL スクリプトの場所を指定する必要があります。 これらのプロパティは、配置先環境に関係なく同一のものとなります。 sqlcmd コマンドを実行するための MSBuild ターゲットを作成する必要もあります。

<PropertyGroup>
   <SqlCmdExe Condition=" '$(SqlCmdExe)'=='' ">
      C:\Program Files\Microsoft SQL Server\100\Tools\Binn\sqlcmd.exe
   </SqlCmdExe>
</PropertyGroup>

<Target Name="DeployTestDBPermissions" 
        Condition=" '$(DeployTestDBRoleMemberships)'=='true' AND 
                    '$(Whatif)'!='true' ">
   <PropertyGroup>
     <SqlScript>
        $(SourceRoot)ContactManager.Database\Scripts\Test\AddRoleMemberships.sql
     </SqlScript>
     <_Cmd>"$(SqlCmdExe)" -S "$(DatabaseServer)" 
                          -d "$(CmTargetDatabase)" 
                          -i "$(SqlScript)"
     </_Cmd>
   </PropertyGroup>
   <Exec Command="$(_Cmd)" ContinueOnError="false" />
</Target>

sqlcmd 実行可能ファイルの場所を静的プロパティとして追加することに注意してください。これは他のターゲットにとって便利な方法です。 これに対し、SQL スクリプトの場所と sqlcmd コマンドの構文は、ターゲットが実行されるまで必要にならないため、ターゲット内の動的プロパティとして定義します。 この場合、DeployTestDBPermissions ターゲットは、以下の条件が満たされた場合にのみ実行されます。

  • DeployTestDBRoleMemberships プロパティが true に設定されている。
  • ユーザーが WhatIf=true フラグを指定しなかった。

最後に、ターゲットを呼び出すのを忘れないでください。 Publish.proj ファイルで、既定の FullPublish ターゲットの依存関係リストにターゲットを追加することでこれを実行できます。 DeployTestDBPermissions ターゲットは、PublishDbPackages ターゲットの実行が完了するまで実行されないようにする必要があります。

<Project ToolsVersion="4.0" 
         DefaultTargets="FullPublish" 
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   ...
   <PropertyGroup>
      <FullPublishDependsOn>
         Clean;
         BuildProjects;
         GatherPackagesForPublishing;
         PublishDbPackages;
         DeployTestDBPermissions;
         PublishWebPackages;
      </FullPublishDependsOn>
   </PropertyGroup>
   <Target Name="FullPublish" DependsOnTargets="$(FullPublishDependsOn)" />
</Project>

まとめ

このトピックでは、データベース プロジェクトをデプロイするときの配置後アクションとしてデータベース ユーザーとロール メンバーシップを追加する 1 つの方法について説明しました。 これは通常、テスト環境内でデータベースを定期的に再作成する場合に便利ですが、データベースをステージングまたは運用環境にデプロイする場合には通常回避する必要があります。 そのため、データベース ユーザーとロール メンバーシップを作成するのはそれが適切な場合だけとなるように、必要な条件付きロジックを使用していることを確認する必要があります。

もっと読む

VSDBCMD を使用してデータベース プロジェクトをデプロイする方法の詳細については、「データベース プロジェクトのデプロイ」を参照してください。 さまざまなターゲット環境用のデータベース デプロイのカスタマイズのガイダンスについては、「複数の環境用のデータベース デプロイのカスタマイズ」を参照してください。 カスタム MSBuild プロジェクト ファイルを使用して配置プロセスを制御する方法の詳細については、「プロジェクト ファイルについて」および「ビルド処理について理解する」を参照してください。 sqlcmd コマンドライン オプションの詳細については、「sqlcmd ユーティリティ」を参照してください。