データベースの開発と配置のための戦略 (C#)

作成者: Scott Mitchell

初めてデータ ドリブン アプリケーションをデプロイする場合は、開発環境のデータベースを運用環境に盲目的にコピーできます。 ただし、後続のデプロイでブラインド コピーを実行すると、運用データベースに入力されたすべてのデータが上書きされます。 代わりに、データベースをデプロイするには、前回のデプロイ以降に開発データベースに加えられた変更を運用データベースに適用する必要があります。 このチュートリアルでは、これらの課題を調べ、前回のデプロイ以降に行われた変更の記録とデータベースへの適用に役立つさまざまな戦略を提供します。

はじめに

前のチュートリアルで説明したように、ASP.NET アプリケーションを展開するには、開発環境から運用環境に関連するコンテンツをコピーする必要があります。 展開は 1 回限りのイベントではなく、新しいバージョンのソフトウェアがリリースされるたびに、またはバグやセキュリティ上の懸念が特定され、対処されるたびに発生します。 ページ、イメージ、JavaScript ファイルなどの ASP.NET ファイルを運用環境にコピーする場合は、これらのファイルが前回のデプロイ以降にどのように変更されたかについて心配する必要はありません。 ファイルを運用環境に盲目的にコピーし、既存のコンテンツを上書きできます。 残念ながら、このシンプルさは、データベースのデプロイには拡張されません。

初めてデータ ドリブン アプリケーションをデプロイする場合は、開発環境のデータベースを運用環境に盲目的にコピーできます。 ただし、後続のデプロイでブラインド コピーを実行すると、運用データベースに入力されたすべてのデータが上書きされます。 代わりに、データベースをデプロイするには、前回のデプロイ以降に開発データベースに加えられた 変更 を運用データベースに適用する必要があります。 このチュートリアルでは、これらの課題を調べ、前回のデプロイ以降に行われた変更の記録とデータベースへの適用に役立つさまざまな戦略を提供します。

データベースの配置に関する課題

データ ドリブン アプリケーションが初めてデプロイされる前は、データベースが 1 つだけ存在します。つまり、開発環境内のデータベースであるため、初めてデータ ドリブン アプリケーションをデプロイするときに、開発環境内のデータベースを運用環境に盲目的にコピーできます。 ただし、アプリケーションがデプロイされると、データベースのコピーが 2 つ存在します。1 つは開発中で、もう 1 つは運用環境です。

デプロイ間で、開発データベースと運用データベースが同期しなくなる可能性があります。運用データベースのスキーマは変更されませんが、新しい機能が追加されると、開発データベースのスキーマが変更される可能性があります。 列、テーブル、ビュー、またはストアド プロシージャを追加または削除できます。 また、開発データベースに追加される重要なデータもあります。 多くのデータ ドリブン アプリケーションには、ユーザーが編集できないハードコーディングされたアプリケーション固有のデータが設定された参照テーブルが含まれます。 たとえば、オークション Web サイトにはドロップダウン リストがあり、オークションに出品されるアイテムの条件を示す選択肢が表示される場合があります。新規、新規、Good、Fair などです。 これらのオプションをドロップダウン リストに直接ハードコーディングするのではなく、通常はデータベース テーブルに配置することをお勧めします。 開発中に Poor という名前の新しい条件がテーブルに追加された場合、アプリケーションをデプロイするときに、この同じレコードを運用データベースの参照テーブルに追加する必要があります。

理想的には、データベースをデプロイするには、開発から運用にデータベースをコピーする必要があります。 ただし、アプリケーションをデプロイして開発を再開すると、実稼働データベースに実際のユーザーからの実際のデータが設定されることに注意してください。 そのため、次のデプロイで開発から運用にデータベースをコピーするだけで、運用データベースが上書きされ、既存のデータが失われます。 その結果、データベースをデプロイすると、前回のデプロイ以降に行われた変更が開発データベースに適用されます。

データベースのデプロイにはスキーマの変更の適用と、最後のデプロイ以降のデータの適用が含まれるため、変更の履歴を維持 (またはデプロイ時に決定) して、運用環境で変更を適用できるようにする必要があります。 データ モデルに対する変更の管理と適用には、さまざまな手法があります。

ベースラインの定義

アプリケーションのデータベースに対する変更を維持するには、何らかの開始状態 (変更が適用されるベースライン) が必要です。 ある極端な場合、開始状態は、テーブル、ビュー、またはストアド プロシージャのない空のデータベースである可能性があります。 このようなベースラインでは、データベースのすべてのテーブル、ビュー、ストアド プロシージャの作成と、初期デプロイ後に行われた変更を含める必要があるため、大きな変更ログが生成されます。 スペクトルのもう一方の端では、最初に運用環境にデプロイされるデータベースのバージョンとしてベースラインを設定できます。 この選択により、最初のデプロイの後にデータベースに加えられた変更のみが含まれるため、変更ログは大幅に小さくなります。 これは私が好むアプローチです。 もちろん、最初のデータベースの作成とデータベースの最初のデプロイの間のポイントとしてベースラインを定義して、より道の途中のアプローチを選択できます。

ベースラインを選択したら、ベースライン バージョンを再作成するために実行できる SQL スクリプトを生成することを検討してください。 このようなスクリプトを使用すると、データベースのベースライン バージョンをすばやく再作成できます。 この機能は、大規模なプロジェクトで特に役立ちます。プロジェクトに複数の開発者が作業している場合や、テストやステージングなどの追加の環境で、それぞれがデータベースの独自のコピーを必要とする場合があります。

ベースライン バージョンの SQL スクリプトを生成するためのさまざまなツールが自由に用意されています。 SQL Server Management Studio (SSMS) から、データベースを右クリックし、[タスク] サブメニューに移動し、[スクリプトの生成] オプションを選択します。 これによりスクリプト ウィザードが起動します。このウィザードでは、データベースのオブジェクトを作成するための SQL コマンドを含むファイルを生成するように指示できます。 もう 1 つのオプションはデータベース発行ウィザードです。SQL コマンドを生成して、データベース スキーマだけでなく、データベース テーブル内のデータも作成できます。 データベース発行ウィザードは、 データベースの配置 に関するチュートリアルで詳しく調べられました。 使用するツールに関係なく、最終的には、必要に応じて、データベースのベースライン バージョンを再作成するために使用できるスクリプト ファイルが必要です。

Prose でのデータベースの変更の文書化

開発フェーズ中にデータ モデルに対する変更のログを保持する最も簡単な方法は、prose の変更を記録することです。 たとえば、既にデプロイされているアプリケーションの開発中に、テーブルに新しい列を追加しEmployees、テーブルからOrders列を削除し、新しいテーブル (ProductCategories) を追加する場合は、次の履歴を含むテキスト ファイルまたは Microsoft Word ドキュメントを保持します。

日付の変更 変更の詳細
2009-02-03: テーブルに列 DepartmentID (int、NOT NULL) を Employees 追加しました。 から への外部キー制約 Departments.DepartmentIDEmployees.DepartmentID追加しました。
2009-02-05: テーブルから列 TotalWeightOrders 削除しました。 関連付けられた OrderDetails レコードに既にキャプチャされているデータ。
2009-02-12: テーブルを作成しました ProductCategories 。 (、)、(nvarchar(50)、) CategoryNameNOT NULLIDENTITYNOT NULLおよび Active (intbitNOT NULL) の 3 つの列 ProductCategoryID があります。 に主キー制約を ProductCategoryID追加し、既定値の 1 を に Active追加しました。

この方法にはいくつかの欠点があります。 まず、自動化の希望はありません。 これらの変更をデータベースに適用する必要がある場合 (アプリケーションのデプロイ時など)、開発者は変更を 1 つずつ手動で実装する必要があります。 さらに、変更ログを使用してベースラインから特定のバージョンのデータベースを再構築する必要がある場合は、ログのサイズが大きくなるにつれて、さらに時間がかかります。 この方法のもう 1 つの欠点は、各変更ログ エントリの明確さと詳細レベルが、変更を記録しているユーザーに任されていることです。 複数の開発者がいるチームでは、他の開発者よりも詳細で読みやすく、より正確なエントリを作成する場合があります。 また、入力ミスやその他の人間関連のデータ入力エラーが発生する可能性があります。

prose でデータベースの変更を文書化する主な利点は、シンプルさです。 データベース オブジェクトを作成および変更するための SQL 構文に精通している必要はありません。 代わりに、prose の変更を記録し、SQL Server Management Studioのグラフィカル ユーザー インターフェイスを使用して実装できます。

prose で変更ログを維持することは、確かに、あまり洗練されておらず、スコープが大きいプロジェクトや、データ モデルに頻繁に変更を加えるプロジェクト、複数の開発者が関与するプロジェクトなど、特定のプロジェクトではうまく機能しません。 しかし、私はこのアプローチが、データモデルに時折変更を加えるだけで、ソロ開発者がデータベースオブジェクトを作成および変更するためのSQL構文に強い背景を持っていない小さな一人称プロジェクトで非常にうまく機能することを見てきました。

注意

変更ログの情報は技術的にはデプロイ時までしか必要ではありませんが、変更の履歴を保持することをお勧めします。 ただし、増え続ける変更ログ ファイルを 1 つ保持するのではなく、データベースのバージョンごとに異なる変更ログ ファイルを使用することを検討してください。 通常は、データベースがデプロイされるたびにバージョンを変更する必要があります。 変更ログのログを保持することで、ベースラインから始めて、バージョン 1 から変更ログ スクリプトを実行し、再作成する必要があるバージョンに達するまで続行することで、データベース のバージョンを再作成できます。

SQL 変更ステートメントの記録

prose で変更ログを維持することの主な欠点は、自動化の欠如です。 理想的には、デプロイ時に運用データベースに対するデータベースの変更を実装するのは、手順の一覧を手動で実行するのではなく、スクリプトを実行するボタンをクリックするのと同じくらい簡単です。 このような自動化は、データ モデルの変更に使用される SQL コマンドを含む変更ログを保持することで可能です。

SQL 構文には、さまざまなデータベース オブジェクトを作成および変更するためのステートメントが多数含まれています。 たとえば、 CREATE TABLE ステートメントを実行すると、指定された列と制約を持つ新しいテーブルが作成されます。 ALTER TABLE ステートメントは、既存のテーブルを変更し、その列または制約を追加、削除、または変更します。 インデックス、ビュー、ユーザー定義関数、ストアド プロシージャ、トリガー、およびその他のデータベース オブジェクトを作成、変更、および削除するステートメントもあります。

前の例に戻ると、既にデプロイされているアプリケーションの開発中に、テーブルに新しい列を追加し Employees 、テーブルから Orders 列を削除し、新しいテーブル (ProductCategories) を追加したイメージが返されます。 このようなアクションを実行すると、次の SQL コマンドを使用して変更ログ ファイルが生成されます。

-- Add the DepartmentID column 

ALTER TABLE [Employees] ADD [DepartmentID] 
int NOT NULL 

-- Add a foreign key constraint between Departments.DepartmentID and Employees.DepartmentID
ALTER TABLE [Employees] ADD 
CONSTRAINT [FK_Departments_DepartmentID]
      FOREIGN 
KEY ([DepartmentID]) 
      REFERENCES 
[Departments] ([DepartmentID]) 

-- Remove TotalWeight column from Orders
ALTER TABLE [Orders] DROP COLUMN 
[TotalWeight] 

-- Create the ProductCategories table

CREATE TABLE [ProductCategories]
(
      [ProductCategoryID] 
int IDENTITY(1,1) NOT NULL,
      [CategoryName] 
nvarchar(50) NOT NULL,
      [Active] 
bit NOT NULL CONSTRAINT [DF_ProductCategories_Active]  DEFAULT 
((1)),
      CONSTRAINT 
[PK_ProductCategories] PRIMARY KEY CLUSTERED ( [ProductCategoryID])
)

これらの変更をデプロイ時に運用データベースにプッシュするのは、ワンクリック操作です。SQL Server Management Studioを開く、運用データベースに接続する、新しいクエリ ウィンドウを開く、変更ログの内容を貼り付ける、および [実行] をクリックしてスクリプトを実行します。

比較ツールを使用したデータ モデルの同期

prose でのデータベース変更の文書化は簡単ですが、変更を実装するには、開発者が運用データベースで一度に 1 つずつ変更を行う必要があります。変更 SQL コマンドを文書化すると、これらの変更を運用データベースに簡単かつ迅速に実装できますが、データベース オブジェクトを作成および変更するには SQL ステートメントと構文を学習して習得する必要があります。 データベース比較ツールは、両方のアプローチから最適な方法を取り、最悪の事態を破棄します。

データベース比較ツールは、2 つのデータベースのスキーマまたはデータを比較し、データベースの違いを示す概要レポートを表示します。 その後、ボタンをクリックすると、1 つ以上のデータベース オブジェクトを同期するための SQL コマンドを生成できます。 簡単に言うと、データベース比較ツールを使用すると、デプロイ時に開発データベースと運用データベースを比較し、SQL コマンドを含むファイルを生成できます。このファイルは、実行時に、開発データベースのスキーマをミラーリングするように運用データベースのスキーマに変更を適用します。

多くの異なるベンダーによって提供されるさまざまなサードパーティデータベース比較ツールがあります。 そのような例の 1 つは、Red Gate Software による SQL Compare です。 SQL Compare を使用して、開発データベースと運用データベースのスキーマを比較および同期するプロセスについて説明します。

注意

この記事の執筆時点では、SQL Compare の現在のバージョンはバージョン 7.1 で、Standard Edition のコストは 395 ドルでした。 14 日間の無料試用版をダウンロードして、フォローできます。

SQL Compare が起動すると、[比較プロジェクト] ダイアログ ボックスが開き、保存された SQL Compare プロジェクトが表示されます。 新しいプロジェクトを作成します。 これにより、Project Configuration ウィザードが起動し、比較するデータベースに関する情報を求められます (図 1 を参照)。 開発環境データベースと運用環境データベースの情報を入力します。

開発データベースと運用データベースを比較する

図 1: 開発データベースと運用データベースを比較する (クリックするとフルサイズの画像が表示されます)

注意

開発環境データベースが Web サイトのフォルダーにある App_Data SQL Express Edition データベース ファイルの場合は、図 1 に示すダイアログ ボックスからデータベースを選択するために、データベースを SQL Server Express データベース サーバーに登録する必要があります。 これを行う最も簡単な方法は、SQL Server Management Studio (SSMS) を開き、SQL Server Express データベース サーバーに接続し、データベースをアタッチすることです。 お使いのコンピューターに SSMS がインストールされていない場合は、無料のSQL Server Management Studioをダウンロードしてインストールできます。

比較するデータベースを選択するだけでなく、[オプション] タブからさまざまな比較設定を指定することもできます。有効にするオプションの 1 つは、"制約名とインデックス名を無視する" です。前のチュートリアルでは、アプリケーション サービス データベース オブジェクトを開発データベースと運用データベースに追加したことを思い出してください。 このツールを aspnet_regsql.exe 使用して運用データベースにこれらのオブジェクトを作成した場合、主キーと一意の制約名が開発データベースと運用データベースで異なることがわかります。 その結果、SQL Compare は、すべてのアプリケーション サービス テーブルに異なるフラグを設定します。 [制約とインデックス名を無視する] をオフのままにして制約名を同期するか、SQL Compare にこれらの違いを無視するように指示できます。

比較するデータベースを選択し、比較オプションを確認したら、[今すぐ比較] ボタンをクリックして比較を開始します。 次の数秒間、SQL Compare は 2 つのデータベースのスキーマを調べ、それらがどのように異なるかについてのレポートを生成します。 SQL Compare インターフェイスでこのような不一致がどのように認識されるかを示すために、開発データベースに意図的にいくつかの変更を加えました。 図 2 に示すように、テーブルに列をBirthDateAuthors追加し、テーブルからBooks列をISBN削除し、新しいテーブル を追加しました。これは、Ratingsユーザーがサイトにアクセスしてレビューされた書籍を評価できるようにするためです。

注意

このチュートリアルで行ったデータ モデルの変更は、データベース比較ツールを使用して説明するために行われました。 これらの変更は、今後のチュートリアルではデータベースに見つかりません。

SQL 比較Lists開発データベースと運用データベースの違い

図 2: SQL 比較 Lists開発データベースと運用データベースの違い (フルサイズの画像を表示する をクリックします)

SQL Compare を使用すると、データベース オブジェクトがグループに分割され、両方のデータベースに存在するが異なるオブジェクト、一方のデータベースに存在するが他方のデータベースに存在しないオブジェクト、同一のオブジェクトをすばやく表示できます。 ご覧のように、両方のデータベースに存在するが異なる Authors 2 つのオブジェクトがあります。列が追加されたテーブルと Books 、削除されたテーブルです。 開発データベースにのみ存在するオブジェクト (新しく作成 Ratings されたテーブル) が 1 つあります。 また、両方のデータベースで同じ 117 個のオブジェクトがあります。

データベース オブジェクトを選択すると、[SQL の相違点] ウィンドウが表示され、これらのオブジェクトがどのように異なるかを示します。 図 2 の下部に表示される [SQL の相違点] ウィンドウでは、開発データベースBirthDateのテーブルに列があり、実稼働データベースのAuthorsテーブルには見つからないことがAuthors強調表示されています。

相違点を確認し、同期するオブジェクトを選択した後、次の手順では、開発データベースと一致するように運用データベースのスキーマを更新するために必要な SQL コマンドを生成します。 これは、同期ウィザードを使用して行われます。 同期ウィザードは、同期するオブジェクトを確認し、アクション プランを要約します (図 3 を参照)。 データベースを直ちに同期したり、スクリプトを生成したり、自由に実行できる SQL コマンドを使用したりできます。

同期ウィザードを使用してデータベース スキーマを同期する

図 3: 同期ウィザードを使用してデータベース スキーマを同期する (クリックするとフルサイズの画像が表示されます)

Red Gate Software の SQL Compare などのデータベース比較ツールを使用すると、開発データベース スキーマへの変更を実稼働データベースにポイントアンドクリックで簡単に適用できます。

注意

SQL Compare では、2 つのデータベース スキーマを比較して同期 します。 残念ながら、2 つのデータベース テーブル内のデータは比較および同期されません。 Red Gate Software は、2 つのデータベース間でデータを比較および同期する SQL Data Compare という名前の製品を提供していますが、SQL Compare とは別の製品であり、別の $395 のコストがかかります。

展開中にアプリケーションをオフラインにする

これらのチュートリアルで説明したように、デプロイは複数の手順を含むプロセスです。ASP.NET ページ、マスター ページ、CSS ファイル、JavaScript ファイル、イメージ、およびその他の必要なコンテンツを開発環境から運用環境にコピーします。必要に応じて、運用環境固有の構成情報をコピーする。最後のデプロイ以降のデータ モデルへの変更の適用。 ファイルの数とデータベースの変更の複雑さに応じて、これらの手順が完了するまでに数秒から数分かかる場合があります。 この期間中、Web アプリケーションは流動的であり、サイトにアクセスするユーザーにエラーや予期しない動作が発生する可能性があります。

Web サイトをデプロイするときは、デプロイが完了するまで Web アプリケーションを "オフライン" にすることをお勧めします。 アプリケーションをオフラインにして (展開プロセスが完了したら)、ファイルをアップロードして削除するのと同じくらい簡単です。 ASP.NET 2.0 以降では、アプリケーションのルート ディレクトリに という名前 app_offline.htm のファイルが存在するだけで、Web サイト全体が "オフライン" になります。そのサイトの ASP.NET ページに対する要求は、ファイルの内容で自動的に app_offline.htm 応答されます。 そのファイルが削除されると、アプリケーションはオンラインに戻ります。

デプロイ中にアプリケーションをオフラインにするのは、デプロイプロセスを開始する app_offline.htm 前に運用環境のルート ディレクトリにファイルをアップロードしてから、デプロイが完了したら削除する (または名前を変更する) のと同じくらい簡単です。 この手法の詳細については、John Peterson の記事「 ASP.NET アプリケーションをオフラインにする」を参照してください。

まとめ

データ ドリブン アプリケーションのデプロイにおけるメインの課題は、データベースのデプロイを中心にしています。 データベースには 2 つのバージョン (開発環境に 1 つ、運用環境に 1 つ) があるため、これら 2 つのデータベース スキーマは、開発中に新機能が追加されると同期しなくなる可能性があります。 さらに、実稼働データベースには実際のユーザーからの実際のデータが設定されているため、アプリケーションを構成するファイル (ASP.NET ページ、イメージ ファイルなど) をデプロイする場合と同様に、運用データベースを変更された開発データベースで上書きすることはできません。 代わりに、データベースをデプロイするには、前回のデプロイ以降に実稼働データベース上の開発データベースに対して行われた正確な一連の変更を実装する必要があります。

このチュートリアルでは、データベース変更のログを維持および適用するための 3 つの手法について説明しました。 最も簡単な方法は、散文の変更を記録することです。 この方法により、運用データベースにこれらの変更を実装することは手動プロセスになりますが、データベース オブジェクトを作成および変更するための SQL コマンドに関する知識は必要ありません。 より洗練されたアプローチと、複数の開発者を持つ大規模なプロジェクトやプロジェクトではるかにわかりやすいアプローチは、一連の SQL コマンドとして変更を記録することです。 これにより、ターゲット データベースに対するこれらの変更のロールアウトが大幅に急がされます。 両方の方法のベストは、Red Gate Software の SQL Compare などのデータベース比較ツールを使用することで実現できます。

このチュートリアルでは、データドリブン アプリケーションのデプロイに重点を置いて説明します。 次の一連のチュートリアルでは、運用環境のエラーに対応する方法について説明します。 黄色い死の画面ではなく、わかりやすいエラー ページを表示する方法について説明します。 また、エラーの詳細をログに記録する方法と、そのようなエラーが発生したときにアラートを生成する方法について説明します。

幸せなプログラミング!