Visual Studio または Visual Web Developer を使用した SQL Server Compact を使用した ASP.NET Web アプリケーションの展開: SQL Server Compact データベースの配置 - 2/12

著者: Tom Dykstra

スターター プロジェクトのダウンロード

このチュートリアル シリーズでは、Visual Studio 2012 RC または Visual Studio Express 2012 RC for Web を使用して、SQL Server Compact データベースを含む ASP.NET Web アプリケーション プロジェクトを、デプロイ (発行) する方法について説明します。 Web 発行の更新をインストールすれば、Visual Studio 2010 を使用することもできます。 シリーズの概要については、シリーズの最初のチュートリアルを参照してください。

Visual Studio 2012 の RC リリース以降に導入されたデプロイ機能の紹介や、SQL Server Compact 以外の SQL Server エディションのデプロイ方法、Azure App Service Web Apps へのデプロイ方法などを解説したチュートリアルは、「Visual Studio を使用した ASP.NET Web デプロイ」をご覧ください。

概要

このチュートリアルでは、2 つの SQL Server Compact データベースと、デプロイ用のデータベース エンジンを設定する方法について説明します。

データベース アクセスのために、Contoso University アプリケーションでは次のソフトウェアが必要であり (それらは .NET Framework に含まれていないため)、それらをアプリケーションと共に配置する必要があります:

アプリケーションの 2 つのデータベース内のデータベース構造とデータの一部 (すべてではない) もデプロイする必要があります。 通常は、アプリケーションを開発するときに、データベースに、ライブ サイトに配置しないテスト データを入力します。 しかし、配置する必要がある運用データを入力する場合もあります。 このチュートリアルでは、展開時に必要なソフトウェアと正しいデータが含まれるように Contoso University プロジェクトを構成します。

リマインダー: チュートリアルの間、エラー メッセージが表示されたり、うまくいかないことがある場合は、必ずトラブルシューティングに関するページをご確認ください。

SQL Server Compact と SQL Server Express

サンプル アプリケーションでは、SQL Server Compact 4.0 を使用します。 このデータベース エンジンは、Web サイトの比較的新しいオプションです。以前のバージョンの SQL Server Compact は、Web ホスティング環境では機能しません。 SQL Server Compact には、SQL Server Express を使用して開発し、完全な SQL Server に展開する一般的なシナリオと比較して、いくつかの利点があります。 選択したホスティング プロバイダーによっては、SQL Server Compact のデプロイが低コストになる場合があります。一部のプロバイダーでは、完全な SQL Server データベースをサポートするために追加料金が発生するためです。 データベース エンジン自体を Web アプリケーションの一部としてデプロイできるため、SQL Server Compact には追加料金はかかりません。

ただし、その制限事項にも注意する必要があります。 SQL Server Compact では、ストアド プロシージャ、トリガー、ビュー、またはレプリケーションはサポートされていません。 (SQL Server Compact でサポートされていない SQL Server 機能の完全な一覧については、「SQL Server Compact と SQL Server の違い」を参照してください。)また、SQL Server Express および SQL Server データベースのスキーマとデータを操作するために使用できるツールの一部は、SQL Server Compact では機能しません。 たとえば、SQL Server Compact データベースでは、Visual Studio で SQL Server Management Studio または SQL Server Data Tools を使用することはできません。 SQL Server Compact データベースを操作するためのその他のオプションがあります:

  • Visual Studio でサーバー エクスプローラーを使用すると、SQL Server Compact のデータベース操作機能の一部を使用できます。
  • サーバー エクスプローラーよりも多くの機能を備える WebMatrix のデータベース操作機能を使用できます。
  • SQL Server Compact ツールボックスや SQL Compact データおよびスキーマ スクリプト ユーティリティ など、比較的フル機能のサード パーティ製ツールやオープン ソース ツールを使用できます。
  • 独自の DDL (データ定義言語) スクリプトを記述して実行して、データベース スキーマを操作できます。

SQL Server Compact から始めて、ニーズの進化に合わせて後でアップグレードできます。 このシリーズの後のチュートリアルでは、SQL Server Compact から SQL Server Express および SQL Server に移行する方法について説明します。 ただし、新しいアプリケーションを作成していて、近い将来に SQL Server が必要になると予想される場合は、SQL Server または SQL Server Express から開始することをお勧めします。

デプロイ用の SQL Server Compact データベース エンジンの構成

Contoso University アプリケーションのデータ アクセスに必要なソフトウェアは、次の NuGet パッケージをインストールすることによって追加されました:

リンクではこれらのパッケー現在のバージョンが指し示されています。それらは、このチュートリアル用にダウンロードしたスターター プロジェクトでインストールされるバージョンよりも新しい場合があります。 ホスティング プロバイダーにデプロイする場合は、Entity Framework 5.0 以降を使用していることを確認してください。 以前のバージョンの Code First Migrations では完全信頼が必要であり、多くのホスティング プロバイダーでは、アプリケーションは中信頼で実行されます。 中程度の信頼について詳しくは、「テスト環境としての IIS への配置」に関するチュートリアルをご覧ください。

NuGet パッケージのインストールは、通常、アプリケーションでこのソフトウェアを展開するために必要なすべての処理を行います。 場合によっては、ソリューションをビルドするたびに実行される Web.config ファイルの変更や PowerShell スクリプトの追加などのタスクが含まれます。 NuGet を使用せずにこれらの機能 (SQL Server Compact や Entity Framework など) のサポートを追加する場合は、同じ作業を手動で実行できるように、NuGet パッケージのインストールが何を行うかを確認してください。

デプロイを成功させるために行う必要があるすべてを NuGet が処理しないという例外が 1 つあります。 SqlServerCompact NuGet パッケージはビルド後のスクリプトをプロジェクトに追加し、ネイティブ アセンブリをプロジェクトの bin フォルダーの下にある x86 および amd64 サブフォルダーにコピーしますが、スクリプトにはプロジェクト内のこれらのフォルダーは含まれません。 その結果、Web 配置は、プロジェクトに手動で含めない限り、コピー先の Web サイトにコピーしません。 (この動作は既定の展開構成の結果です。これらのチュートリアルでは使用しない別のオプションは、この動作を制御する設定を変更することです。変更できる設定は、[プロジェクトのプロパティ] ウィンドウの [パッケージ/発行 Web] タブの [配置するアイテム]アプリケーションを実行するために必要なファイルのみです。この設定を変更すると、必要以上に多くのファイルが運用環境にデプロイされる可能性があるため、通常は推奨されません。代替方法の詳細については、「プロジェクトのプロパティの構成」チュートリアルを参照してください。)

プロジェクトをビルドし、ソリューション エクスプローラー [すべてのファイルを表示] をクリックします (まだ行っていない場合)。 [最新の情報に更新 ] をクリックする必要がある場合もあります。

Solution_Explorer_Show_All_Files

bin フォルダーを展開して amd64 フォルダーと x86 フォルダーを表示し、それらのフォルダーを選択して右クリックし、[プロジェクトに含める] を選択 します。

amd64_and_x86_in_Solution_Explorer.png

フォルダー アイコンが変更され、フォルダーがプロジェクトに含まれていることが示されます。

Solution_Explorer_amd64_included.png

アプリケーション データベースのデプロイ用にコードファースト移行を構成する

アプリケーション データベースを配置するときは、通常は、すべてのデータを含む開発データベースを運用環境に配置するのではありません。これは、その中のデータの多くはテスト目的でのみ存在する可能性があるためです。 たとえば、テスト データベース内の学生の名前は架空の名前です。 他方で、多くの場合、データをまったく含まずデータベース構造のみを配置することはできません。 テスト データベース内の一部のデータは、実際のデータであり、ユーザーがそのアプリケーションを使い始めるときにそこに存在する必要があります。 たとえば、データベースに、有効な成績値や実際の部署名を含むテーブルがあるとします。

この一般的なシナリオをシミュレートするには、運用環境に存在する必要があるデータのみをデータベースに挿入する、Code First Migrations の シード メソッドを構成します。 この Seed メソッドではテスト データを挿入しないでください。これは、Code First で運用環境にデータベースが作成された後に、運用環境でこのメソッドが実行されるためです。

Migrations がリリースされる前のバージョンの Code First では、Seed メソッドでテスト データを挿入することも一般的でした。これは、開発中にモデルに変更があるたびに、データベースを完全に削除して最初から作り直す必要があったためです。 Code First Migrations では、テスト データはデータベース変更後も保持されます。そのため、Seed メソッドでテスト データを含める必要はありません。 ダウンロードしたプロジェクトでは、初期化子クラスの Seed メソッドにすべてのデータを含める移行前メソッドが使用されます。 このチュートリアルでは、初期化子クラスを無効にし、移行を有効にします。 次に、運用環境に挿入する必要があるデータのみを挿入するように、Migrations 構成クラス内の Seed メソッドを更新します。

次の図は、アプリケーション データベースのスキーマを示しています:

School_database_diagram

これらのチュートリアルでは、サイトを最初に配置するときに Student および Enrollment テーブルが空になっている必要があると仮定します。 他のテーブルには、アプリケーションが稼働し始めるときに事前に読み込まれている必要があるデータが含まれています。

Code First Migrations を使用するため、DropCreateDatabaseIfModelChanges Code First 初期化子を使用する必要がなくなりました。 この初期化子のコードは、ContosoUniversity.DAL プロジェクト内の SchoolInitializer.cs ファイルにあります。 Web.config ファイルの appSettings 要素の設定により、アプリケーションがデータベースに初めてアクセスしようとするたびに、この初期化子が実行されます:

<appSettings>
  <add key="Environment" value="Dev" />
  <add key="DatabaseInitializerForType ContosoUniversity.DAL.SchoolContext, ContosoUniversity.DAL" value="ContosoUniversity.DAL.SchoolInitializer, ContosoUniversity.DAL" />
</appSettings>

アプリケーション Web.config ファイルを開き、Code First 初期化子クラスを指定する要素を appSettings 要素から削除します。 appSettings 要素は次のようになります:

<appSettings>
  <add key="Environment" value="Dev" />
</appSettings>

Note

初期化子クラスを指定するためのもう 1 つの方法は、Global.asax ファイル内の Application_Start メソッドで Database.SetInitializer を呼び出すことです。 プロジェクトで Migrations を有効にしており、そのメソッドを使って初期化子を指定している場合は、そのコード行を削除します。

次に、Code First Migrations を有効にします。

最初の手順は、ContosoUniversity プロジェクトがスタートアップ プロジェクトとして設定されていることを確認することです。 ソリューション エクスプローラーで、ContosoUniversity プロジェクトを右クリックし、[スタートアップ プロジェクトに設定] を選択します。 Code First Migrations で、スタートアップ プロジェクト内でデータベース接続文字列が検索されます。

[ツール] メニューで [NuGet パッケージ マネージャー][パッケージ マネージャー コンソール] の順にクリックします。

Selecting_Package_Manager_Console

[パッケージ マネージャー コンソール] ウィンドウの上部で、既定のプロジェクトとして ContosoUniversity.DAL を選択してから、PM> プロンプトで「enable-migrations」と入力します。

enable-migrations_command

このコマンドは、ContosoUniversity.DAL プロジェクトの新しい Migrations フォルダーに Configuration.cs ファイルを作成します。

Migrations_folder_in_Solution_Explorer

"enable-migrations" コマンドを、Code First コンテキスト クラスを含むプロジェクトで実行する必要があるため、DAL プロジェクトを選択しました。 そのクラスがクラス ライブラリ プロジェクト内にあると、Code First Migrations で、ソリューションのスタートアップ プロジェクトでデータベース接続文字列が検索されます。 ContosoUniversity ソリューションでは、その Web プロジェクトがスタートアップ プロジェクトとして設定されています。 (接続文字列があるプロジェクトを Visual Studio でのスタートアップ プロジェクトとして指定しない場合は、PowerShell コマンドでスタートアップ プロジェクトを指定できます。enable-migrations コマンドのコマンド構文を確認するには、"get-help enable-migrations" コマンドを入力します。)

Configuration.cs ファイルを開き、Seed メソッド内のコメントを次のコードに置き換えます:

var instructors = new List<Instructor>
{   
    new Instructor { FirstMidName = "Kim",     LastName = "Abercrombie", HireDate = DateTime.Parse("1995-03-11"), OfficeAssignment = new OfficeAssignment { Location = "Smith 17" } },
    new Instructor { FirstMidName = "Fadi",    LastName = "Fakhouri",    HireDate = DateTime.Parse("2002-07-06"), OfficeAssignment = new OfficeAssignment { Location = "Gowan 27" } },
    new Instructor { FirstMidName = "Roger",   LastName = "Harui",       HireDate = DateTime.Parse("1998-07-01"), OfficeAssignment = new OfficeAssignment { Location = "Thompson 304" } },
    new Instructor { FirstMidName = "Candace", LastName = "Kapoor",      HireDate = DateTime.Parse("2001-01-15") },
    new Instructor { FirstMidName = "Roger",   LastName = "Zheng",       HireDate = DateTime.Parse("2004-02-12") }
};
instructors.ForEach(s => context.Instructors.AddOrUpdate(i => i.LastName, s));
context.SaveChanges();

var departments = new List<Department>
{
    new Department { Name = "English",     Budget = 350000, StartDate = DateTime.Parse("2007-09-01"), PersonID = 1 },
    new Department { Name = "Mathematics", Budget = 100000, StartDate = DateTime.Parse("2007-09-01"), PersonID = 2 },
    new Department { Name = "Engineering", Budget = 350000, StartDate = DateTime.Parse("2007-09-01"), PersonID = 3 },
    new Department { Name = "Economics",   Budget = 100000, StartDate = DateTime.Parse("2007-09-01"), PersonID = 4 }
};
departments.ForEach(s => context.Departments.AddOrUpdate(d => d.Name, s));
context.SaveChanges();

var courses = new List<Course>
{
    new Course { CourseID = 1050, Title = "Chemistry",      Credits = 3, DepartmentID = 3, Instructors = new List<Instructor>() },
    new Course { CourseID = 4022, Title = "Microeconomics", Credits = 3, DepartmentID = 4, Instructors = new List<Instructor>() },
    new Course { CourseID = 4041, Title = "Macroeconomics", Credits = 3, DepartmentID = 4, Instructors = new List<Instructor>() },
    new Course { CourseID = 1045, Title = "Calculus",       Credits = 4, DepartmentID = 2, Instructors = new List<Instructor>() },
    new Course { CourseID = 3141, Title = "Trigonometry",   Credits = 4, DepartmentID = 2, Instructors = new List<Instructor>() },
    new Course { CourseID = 2021, Title = "Composition",    Credits = 3, DepartmentID = 1, Instructors = new List<Instructor>() },
    new Course { CourseID = 2042, Title = "Literature",     Credits = 4, DepartmentID = 1, Instructors = new List<Instructor>() }
};
courses.ForEach(s => context.Courses.AddOrUpdate(s));
context.SaveChanges();

courses[0].Instructors.Add(instructors[0]);
courses[0].Instructors.Add(instructors[1]);
courses[1].Instructors.Add(instructors[2]);
courses[2].Instructors.Add(instructors[2]);
courses[3].Instructors.Add(instructors[3]);
courses[4].Instructors.Add(instructors[3]);
courses[5].Instructors.Add(instructors[3]);
courses[6].Instructors.Add(instructors[3]);
context.SaveChanges();

List への参照の下には赤い波線があります。これは、その名前空間の using ステートメントがまだないためです。 List のインスタンスの 1 つを右クリックし、[解決] をクリックしてから、[System.Collections.Generic の使用] をクリックします。

Resolve with using statement

このメニューを選択すると、ファイルの先頭付近の using ステートメントに次のコードが追加されます。

using System.Collections.Generic;

Note

Seed メソッドへのコードの追加は、固定データをデータベースに挿入するための多数の方法の 1 つです。 別の方法としては、各移行クラスの Up および Down メソッドへのコードの追加があります。 Up および Down メソッドには、データベースの変更点を実装するコードが含まれています。 これらの例については、「データベース更新の配置」チュートリアルをご覧ください。

Sql メソッドを使って SQL ステートメントを実行するコードを記述することもできます。 たとえば、Department テーブルに Budget 列を追加していて、移行の一環としてすべての部門予算 (department budget) を 1,000.00 ドルに初期化する場合は、その移行の Up メソッドに次のコード行を追加します:

Sql("UPDATE Department SET Budget = 1000");

このチュートリアルで示すこの例では、Code First Migrations Configuration クラスの Seed メソッドの AddOrUpdate メソッドを使用します。 Code First Migrations は、すべての移行後に Seed メソッドを呼び出します。このメソッドは、既に挿入されている行を更新するか、まだ存在しない場合は挿入します。 AddOrUpdate メソッドは、ご自分のシナリオに最適な選択肢ではない場合があります。 詳しくは、Julie Lerman のブログで、EF 4.3 の AddOrUpdate メソッドへの対処に関するページをご覧ください。

Ctrl キーと Shift キーを押しながら B キーを押してプロジェクトをビルドします。

次の手順では、最初の移行用の DbMigration クラスを作成します。 この移行で新しいデータベースを作成し、既に存在するデータベースを削除する必要があります。 SQL Server Compact データベースは、App_Data フォルダー内の .sdf ファイルに含まれています。 ソリューション エクスプローラーで、ContosoUniversity プロジェクトの App_Data を展開して、.sdf ファイルで表される 2 つの SQL Server Compact データベースを表示します。

School.sdf ファイルを右クリックし、[削除] をクリックします。

sdf_files_in_Solution_Explorer

パッケージ マネージャー コンソール ウィンドウで、"add-migration Initial" コマンドを入力して初期移行を作成し、"Initial" という名前を付けます。

add-migration_command

Code First Migrations は Migrations フォルダーに別のクラス ファイルを作成し、このクラスにはデータベース スキーマを作成するコードが含まれています。

パッケージ マネージャー コンソールで、"update-database" コマンドを入力してデータベースを作成し、Seed メソッドを実行します。

update-database_command

(テーブルが既に存在し、作成できないことを示すエラーが発生した場合は、データベースを削除した後で、update-database を実行する前にアプリケーションを実行したためである可能性があります。その場合は School.sdf ファイルをもう一度削除し、update-database コマンドを再試行してください。)

アプリケーションを実行します。 [Students] ページは空になりましたが、[Instructors] ページにはインストラクターが含まれています。 これは、アプリケーションをデプロイした後に運用環境で得られるものです。

Empty_Students_page

Instructors_page_after_initial_migration

これで、プロジェクトで School データベースをデプロイする準備ができました。

デプロイ用のメンバーシップ データベースの作成

Contoso University アプリケーションでは、ユーザーの認証と承認に ASP.NET メンバーシップ システムとフォーム認証が使われています。 そのページの 1 つにアクセスできるのは管理者だけです。 このページを表示するには、アプリケーションを実行し、[コース] のポップアップ メニューから [クレジットの更新] を選択します。 [クレジットの更新] ページの使用が管理者のみが承認されているため、アプリケーションに [ログイン] ページが表示されます。

Log_in_page

パスワード "Pas$w0rd" を使用して "admin" としてログインします ("w0rd" の文字 "o" の代わりに 0 を指定してください)。 ログインすると、[クレジットの更新] ページが表示されます。

Update_Credits_page

サイトを初めて配置するときは、テスト用に作成したユーザー アカウントの大部分またはすべてを除外するのが一般的です。 この場合は、管理者アカウントをデプロイし、ユーザー アカウントはデプロイしません。 テスト アカウントを手動で削除するのではなく、運用環境で必要な管理者ユーザー アカウントを 1 つだけ持つ新しいメンバーシップ データベースを作成します。

Note

メンバーシップ データベースには、アカウント パスワードのハッシュが格納されます。 あるマシンから別のマシンにアカウントを配置するには、移行元コンピューター上と異なるハッシュが移行先サーバー上にハッシュ ルーチンで生成されないようにする必要があります。 それらでは、ASP.NET ユニバーサル プロバイダーの使用時は、既定のアルゴリズムを変更しない限り、同じハッシュが生成されます。 既定のアルゴリズムは HMACSHA256 であり、Web.config ファイル内の machineKey 要素の validation 属性で指定されています。

メンバーシップ データベースは Code First Migrations によって管理されず、(School データベースのように) テスト アカウントを使用してデータベースをシードする自動初期化子はありません。 そのため、テスト データを使用できるように、新しいデータベースを作成する前に、テスト データベースのコピーを作成します。

ソリューション エクスプローラーで、App_Data フォルダー内の aspnet.sdf ファイルの名前を aspnet-Dev.sdf に変更します。 (コピーを作成しないで、名前を変更するだけにしてください — すぐに新しいデータベースを作成します。)

ソリューション エクスプローラーで、Web プロジェクト (ContosoUniversity.DAL ではなく ContosoUniversity) が選択されていることを確認します。 次に、[プロジェクト] メニューの [ASP.NET 構成] を選択して、Web サイト管理ツール (WAT) を実行します。

[セキュリティ] タブをクリックします。

WAT_Security_tab

[ロールの作成または管理] をクリックし、管理者ロールを追加します。

WAT_Create_New_Role

[セキュリティ] タブに戻り、[ユーザーの作成] をクリックし、ユーザー "admin" を管理者として追加します。 [ユーザーの作成] ページで [ユーザーの作成] ボタンをクリックする前に、[管理者] チェック ボックスをオンにします。 このチュートリアルで使用するパスワードは "Pas$w0rd" であり、任意の電子メール アドレスを入力できます。

WAT_Create_User

ブラウザーを閉じます。 ソリューション エクスプローラーで、更新ボタンをクリックして、新しい aspnet.sdf ファイルを表示します。

New_aspnet.sdf_in_Solution_Explorer

aspnet.sdf を右クリックし、[プロジェクトに含める] を選択します。

開発と運用データベースの区別

このセクションでは、開発バージョンが School-Dev.sdf と aspnet-Dev.sdf であり、運用バージョンが School-Prod.sdf と aspnet-Prod.sdf になるようにデータベースの名前を変更します。 これは必須ではありませんが、そうすることで、データベースのテストバージョンと実稼働バージョンが混乱するのを防ぐことができます。

ソリューション エクスプローラーで、[最新の情報に更新] をクリックし、App_Data フォルダーを展開して、先ほど作成した School データベースを表示します。右クリックし、[プロジェクトに含める] を選択します。

Including_School.sdf_in_project

aspnet.sdf の名前を aspnet-Prod.sdf に変更します。

School.sdf の名前を School-Dev.sdf に変更します。

Visual Studio でアプリケーションを実行する場合、-Prod バージョンのデータベース ファイルを使用したくない場合は、-Dev バージョンを使用します。 そのため、Web.config ファイル内の接続文字列を変更して、データベースの -Dev バージョンを指すようにする必要があります。 (School-Prod.sdf ファイルは作成していませんが、Code First ではアプリを初めて実行するときに運用環境でそのデータベースが作成されるため、問題ありません。)

アプリケーション Web.config ファイルを開き、接続文字列を見つけます:

<configuration>
  <!-- Settings -->
  <connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=|DataDirectory|aspnet.sdf" providerName="System.Data.SqlServerCe.4.0" />
    <add name="SchoolContext" connectionString="Data Source=|DataDirectory|School.sdf" providerName="System.Data.SqlServerCe.4.0" />
  </connectionStrings>
  <!-- Settings -->
</configuration>

"aspnet.sdf" を "aspnet-Dev.sdf" に変更し、"School.sdf" を "School-Dev.sdf" に変更します:

<configuration>
  <!-- Settings -->
  <connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=|DataDirectory|aspnet-Dev.sdf" providerName="System.Data.SqlServerCe.4.0" />
    <add name="SchoolContext" connectionString="Data Source=|DataDirectory|School-Dev.sdf" providerName="System.Data.SqlServerCe.4.0" />
  </connectionStrings>
  <!-- Settings -->
</configuration>

SQL Server Compact データベース エンジンと両方のデータベースをデプロイする準備ができました。 次のチュートリアルでは、開発環境、テスト環境、および運用環境で異なる必要がある設定に対して、Web.config ファイルの自動変換を設定します。 (変更する必要がある設定の中には接続文字列がありますが、後で発行プロファイルを作成するときにこれらの変更を設定します。)

その他の情報

NuGet について詳しくは、「NuGet でプロジェクト ライブラリを管理する」と NuGet のドキュメントをご覧ください。 NuGet を使わない場合は、NuGet パッケージを分析してそれがインストールされている場合のその動作を特定する方法を学習する必要があります。 (たとえば、それで Web.config 変換が構成される場合や、ビルド時に実行するように PowerShell スクリプトが構成される場合などがあります。)NuGet のしくみについて詳しくは、「パッケージの作成と発行」に関するページと「ソース コードと構成ファイルの変換」をご覧ください。