チュートリアル: ASP.NET MVC アプリで EF Migrations を使用し、Azure にデプロイする

これまで、Contoso University のサンプル Web アプリケーションは、開発用コンピューター上の IIS Express でローカルに実行されています。 実際のアプリケーションを他のユーザーがインターネット経由で使用できるようにするには、Web ホスティング プロバイダーにデプロイする必要があります。 このチュートリアルでは、Code First の移行を有効にし、Azure のクラウドにアプリケーションをデプロイします。

  • Code First Migrationsを有効にします。 移行機能を使用すると、データベースを削除して再作成することなく、データベース スキーマを更新することで、データ モデルを変更し、運用環境に変更をデプロイできます。
  • Azure にデプロイします。 この手順は省略可能です。プロジェクトをデプロイしなくても、残りのチュートリアルを続行できます。

デプロイにはソース管理を使用した継続的インテグレーション プロセスを使用することをお勧めしますが、このチュートリアルではこれらのトピックについては説明しません。 詳細については、「Azure を使用したReal-World Cloud Apps の構築」のソース管理継続的インテグレーションの章を参照してください。

このチュートリアルでは、次の作業を行いました。

  • Code First の移行を有効にする
  • Azure にアプリをデプロイする (省略可能)

前提条件

Code First の移行を有効にする

新しいアプリケーションを開発して、データ モデルが頻繁に変更される場合、モデルが変更されるたびに、モデルはデータベースと同期されなくなります。 データ モデルを変更するたびにデータベースを自動的に削除して再作成するように Entity Framework を構成しました。 エンティティ クラスを追加、削除、または変更したり、クラスを変更したりすると、次回アプリケーションを DbContext 実行すると、既存のデータベースが自動的に削除され、モデルに一致する新しいデータベースが作成され、テスト データがシードされます。

このメソッドは、実稼働環境にアプリケーションを展開するまで、データベースとデータ モデルの同期の維持がうまく機能します。 アプリケーションが運用環境で実行されている場合、通常は保持するデータが格納されるため、新しい列の追加など、変更を加えるたびにすべてを失う必要はありません。 Code First Migrations機能は、Code First でデータベースを削除して再作成するのではなく、データベース スキーマを更新できるようにすることで、この問題を解決します。 このチュートリアルでは、アプリケーションをデプロイし、その準備のために移行を有効にします。

  1. アプリケーション Web.config ファイルに追加した要素をコメントアウトまたは削除 contexts して、前に設定した初期化子を無効にします。

    <entityFramework>
      <!--<contexts>
        <context type="ContosoUniversity.DAL.SchoolContext, ContosoUniversity">
          <databaseInitializer type="ContosoUniversity.DAL.SchoolInitializer, ContosoUniversity" />
        </context>
      </contexts>-->
      <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
        <parameters>
          <parameter value="v11.0" />
        </parameters>
      </defaultConnectionFactory>
      <providers>
        <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
      </providers>
    </entityFramework>
    
  2. また、アプリケーション Web.config ファイルで、接続文字列内のデータベースの名前を ContosoUniversity2 に変更します。

    <connectionStrings>
      <add name="SchoolContext" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=ContosoUniversity2;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
    </connectionStrings>
    

    この変更により、最初の移行で新しいデータベースが作成されるようにプロジェクトが設定されます。 これは必須ではありませんが、後でそれが良いアイデアである理由が表示されます。

  3. [ツール] メニューで、[NuGet パッケージ マネージャー]>[パッケージ マネージャー コンソール] の順に選択します。

  4. プロンプトで、 PM> 次のコマンドを入力します。

    enable-migrations
    add-migration InitialCreate
    

    コマンドは enable-migrations 、ContosoUniversity プロジェクトに Migrations フォルダーを作成し、そのフォルダーに Configuration.cs ファイルを配置します。このファイルは、移行を構成するために編集できます。

    (上記の手順を実行しないと、データベース名を変更するように指示された場合、Migrations によって既存のデータベースが検索され、コマンドが自動的に add-migration 実行されます。これで問題ありません。これは、データベースをデプロイする前に移行コードのテストを実行しないことを意味します。後でコマンドを実行しても、 update-database データベースが既に存在するため、何も起こりません)。)

    ContosoUniversity\Migrations\Configuration.cs ファイルを開きます。 前に見た初期化子クラスと同様に Configuration 、 クラスには メソッドが Seed 含まれています。

    internal sealed class Configuration : DbMigrationsConfiguration<ContosoUniversity.DAL.SchoolContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
        }
    
        protected override void Seed(ContosoUniversity.DAL.SchoolContext context)
        {
            //  This method will be called after migrating to the latest version.
    
            //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
            //  to avoid creating duplicate seed data. E.g.
            //
            //    context.People.AddOrUpdate(
            //      p => p.FullName,
            //      new Person { FullName = "Andrew Peters" },
            //      new Person { FullName = "Brice Lambson" },
            //      new Person { FullName = "Rowan Miller" }
            //    );
            //
        }
    }
    

    Seed メソッドの目的は、Code First でデータベースを作成または更新した後に、テスト データを挿入または更新できるようにすることです。 メソッドは、データベースが作成されるときに呼び出され、データ モデルの変更後にデータベース スキーマが更新されるたびに呼び出されます。

Seed メソッドを設定する

データ モデルの変更ごとにデータベースを削除して再作成する場合は、初期化子クラスの Seed メソッドを使用してテスト データを挿入します。これは、すべてのモデル変更後にデータベースが削除され、すべてのテスト データが失われるためです。 Code First Migrationsでは、データベースの変更後もテスト データが保持されるため、Seed メソッドにテスト データを含める必要はありません。 実際、Migrations を使用してデータベースを Seed 運用環境にデプロイする場合は、 メソッドをテスト データを挿入する必要はありません。これは、 メソッドが運用環境で実行されるためです Seed 。 その場合は、 メソッドを Seed 運用環境で必要なデータのみをデータベースに挿入する必要があります。 たとえば、アプリケーションが運用環境で使用可能になったときに、データベースに実際の部署名を Department テーブルに含めることができます。

このチュートリアルでは、デプロイに移行を使用しますが、多くのデータを Seed 手動で挿入しなくてもアプリケーションの機能がどのように機能するかを簡単に確認できるように、方法ではテスト データを挿入します。

  1. Configuration.cs ファイルの内容を、新しいデータベースにテスト データを読み込む次のコードに置き換えます。

    namespace ContosoUniversity.Migrations
    {
        using ContosoUniversity.Models;
        using System;
        using System.Collections.Generic;
        using System.Data.Entity;
        using System.Data.Entity.Migrations;
        using System.Linq;
    
        internal sealed class Configuration : DbMigrationsConfiguration<ContosoUniversity.DAL.SchoolContext>
        {
            public Configuration()
            {
                AutomaticMigrationsEnabled = false;
            }
    
            protected override void Seed(ContosoUniversity.DAL.SchoolContext context)
            {
                var students = new List<Student>
                {
                    new Student { FirstMidName = "Carson",   LastName = "Alexander", 
                        EnrollmentDate = DateTime.Parse("2010-09-01") },
                    new Student { FirstMidName = "Meredith", LastName = "Alonso",    
                        EnrollmentDate = DateTime.Parse("2012-09-01") },
                    new Student { FirstMidName = "Arturo",   LastName = "Anand",     
                        EnrollmentDate = DateTime.Parse("2013-09-01") },
                    new Student { FirstMidName = "Gytis",    LastName = "Barzdukas", 
                        EnrollmentDate = DateTime.Parse("2012-09-01") },
                    new Student { FirstMidName = "Yan",      LastName = "Li",        
                        EnrollmentDate = DateTime.Parse("2012-09-01") },
                    new Student { FirstMidName = "Peggy",    LastName = "Justice",   
                        EnrollmentDate = DateTime.Parse("2011-09-01") },
                    new Student { FirstMidName = "Laura",    LastName = "Norman",    
                        EnrollmentDate = DateTime.Parse("2013-09-01") },
                    new Student { FirstMidName = "Nino",     LastName = "Olivetto",  
                        EnrollmentDate = DateTime.Parse("2005-08-11") }
                };
                students.ForEach(s => context.Students.AddOrUpdate(p => p.LastName, s));
                context.SaveChanges();
    
                var courses = new List<Course>
                {
                    new Course {CourseID = 1050, Title = "Chemistry",      Credits = 3, },
                    new Course {CourseID = 4022, Title = "Microeconomics", Credits = 3, },
                    new Course {CourseID = 4041, Title = "Macroeconomics", Credits = 3, },
                    new Course {CourseID = 1045, Title = "Calculus",       Credits = 4, },
                    new Course {CourseID = 3141, Title = "Trigonometry",   Credits = 4, },
                    new Course {CourseID = 2021, Title = "Composition",    Credits = 3, },
                    new Course {CourseID = 2042, Title = "Literature",     Credits = 4, }
                };
                courses.ForEach(s => context.Courses.AddOrUpdate(p => p.Title, s));
                context.SaveChanges();
    
                var enrollments = new List<Enrollment>
                {
                    new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Alexander").ID, 
                        CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID, 
                        Grade = Grade.A 
                    },
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Alexander").ID,
                        CourseID = courses.Single(c => c.Title == "Microeconomics" ).CourseID, 
                        Grade = Grade.C 
                     },                            
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Alexander").ID,
                        CourseID = courses.Single(c => c.Title == "Macroeconomics" ).CourseID, 
                        Grade = Grade.B
                     },
                     new Enrollment { 
                         StudentID = students.Single(s => s.LastName == "Alonso").ID,
                        CourseID = courses.Single(c => c.Title == "Calculus" ).CourseID, 
                        Grade = Grade.B 
                     },
                     new Enrollment { 
                         StudentID = students.Single(s => s.LastName == "Alonso").ID,
                        CourseID = courses.Single(c => c.Title == "Trigonometry" ).CourseID, 
                        Grade = Grade.B 
                     },
                     new Enrollment {
                        StudentID = students.Single(s => s.LastName == "Alonso").ID,
                        CourseID = courses.Single(c => c.Title == "Composition" ).CourseID, 
                        Grade = Grade.B 
                     },
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Anand").ID,
                        CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID
                     },
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Anand").ID,
                        CourseID = courses.Single(c => c.Title == "Microeconomics").CourseID,
                        Grade = Grade.B         
                     },
                    new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Barzdukas").ID,
                        CourseID = courses.Single(c => c.Title == "Chemistry").CourseID,
                        Grade = Grade.B         
                     },
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Li").ID,
                        CourseID = courses.Single(c => c.Title == "Composition").CourseID,
                        Grade = Grade.B         
                     },
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Justice").ID,
                        CourseID = courses.Single(c => c.Title == "Literature").CourseID,
                        Grade = Grade.B         
                     }
                };
    
                foreach (Enrollment e in enrollments)
                {
                    var enrollmentInDataBase = context.Enrollments.Where(
                        s =>
                             s.Student.ID == e.StudentID &&
                             s.Course.CourseID == e.CourseID).SingleOrDefault();
                    if (enrollmentInDataBase == null)
                    {
                        context.Enrollments.Add(e);
                    }
                }
                context.SaveChanges();
            }
        }
    }
    

    Seed メソッドはデータベース コンテキスト オブジェクトを入力パラメーターとして受け取り、メソッドのコードはそのオブジェクトを使用して新しいエンティティをデータベースに追加します。 エンティティの種類ごとに、新しいエンティティのコレクションを作成し、適切な DbSet プロパティに追加してから、変更をデータベースに保存します。 ここで説明するように、エンティティの各グループの後に SaveChanges メソッドを呼び出す必要はありませんが、これを行うと、コードがデータベースに書き込んでいる間に例外が発生した場合に問題の原因を特定するのに役立ちます。

    データを挿入するステートメントの一部では、 AddOrUpdate メソッドを使用して "upsert" 操作を実行します。 メソッドは Seed コマンドを実行するたびに実行 update-database されるため、通常は移行ごとにデータを挿入することはできません。追加しようとしている行は、データベースを作成する最初の移行後に既に存在するためです。 "upsert" 操作では、既に存在する行を挿入しようとした場合に発生するエラーを防ぐことができますが、アプリケーションのテスト中に行った可能性のあるデータに対する変更は オーバーライド されます。 一部のテーブルのテスト データでは、そのようなことが起こらない可能性があります。テスト中にデータを変更する場合は、データベースの更新後も変更を保持する必要があります。 その場合は、条件付き挿入操作を実行します。行がまだ存在しない場合にのみ行を挿入します。 Seed メソッドでは、両方の方法が使用されます。

    AddOrUpdate メソッドに渡される最初のパラメーターは、行が既に存在する場合にチェックするために使用するプロパティを指定します。 指定するテスト学生データの場合、リスト内の LastName 各姓は一意であるため、 プロパティをこの目的に使用できます。

    context.Students.AddOrUpdate(p => p.LastName, s)
    

    このコードは、姓が一意であることを前提としています。 姓が重複する学生を手動で追加すると、次に移行を実行するときに次の例外が発生します。

    シーケンスに複数の要素が含まれている

    "Alexander Carson" という名前の 2 人の学生などの冗長データを処理する方法については、Rick Anderson のブログの「 Entity Framework (EF) DB のシード処理とデバッグ」を 参照してください。 メソッドの AddOrUpdate 詳細については、Julie Lerman のブログの 「EF 4.3 AddOrUpdate メソッドに注意 する」を参照してください。

    エンティティを作成 Enrollment するコードでは、コレクション内の ID エンティティ students に値があることを前提としていますが、コレクションを作成するコードではそのプロパティを設定していません。

    new Enrollment { 
        StudentID = students.Single(s => s.LastName == "Alexander").ID, 
        CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID, 
        Grade = Grade.A 
    },
    

    このプロパティは、コレクションをID呼び出SaveChangesすときにID値が設定されるため、studentsここで使用できます。 EF は、エンティティをデータベースに挿入すると、主キー値を自動的に取得し、メモリ内のエンティティのプロパティを更新 ID します。

    Enrollment エンティティをエンティティ セットに追加する Enrollments コードでは、 メソッドは AddOrUpdate 使用されません。 エンティティが既に存在するかどうかを確認し、存在しない場合はエンティティを挿入します。 この方法では、アプリケーション UI を使用して登録グレードに加えた変更が保持されます。 このコードは List の各メンバーをEnrollmentループ処理し、登録がデータベースに見つからない場合は、登録をデータベースに追加します。 データベースを初めて更新すると、データベースは空になるため、各登録が追加されます。

    foreach (Enrollment e in enrollments)
    {
        var enrollmentInDataBase = context.Enrollments.Where(
            s => s.Student.ID == e.Student.ID &&
                 s.Course.CourseID == e.Course.CourseID).SingleOrDefault();
        if (enrollmentInDataBase == null)
        {
            context.Enrollments.Add(e);
        }
    }
    
  2. プロジェクトをビルドします。

最初の移行を実行する

コマンドを add-migration 実行すると、Migrations によってデータベースを最初から作成するコードが生成されました。 このコードは、timestamp>_InitialCreate.cs という名前<のファイルの Migrations フォルダーにも含まれています。 クラスの InitialCreate メソッドはUp、データ モデル エンティティ セットに対応するデータベース テーブルを作成しDown、それらを削除します。

public partial class InitialCreate : DbMigration
{
    public override void Up()
    {
        CreateTable(
            "dbo.Course",
            c => new
                {
                    CourseID = c.Int(nullable: false),
                    Title = c.String(),
                    Credits = c.Int(nullable: false),
                })
            .PrimaryKey(t => t.CourseID);
        
        CreateTable(
            "dbo.Enrollment",
            c => new
                {
                    EnrollmentID = c.Int(nullable: false, identity: true),
                    CourseID = c.Int(nullable: false),
                    StudentID = c.Int(nullable: false),
                    Grade = c.Int(),
                })
            .PrimaryKey(t => t.EnrollmentID)
            .ForeignKey("dbo.Course", t => t.CourseID, cascadeDelete: true)
            .ForeignKey("dbo.Student", t => t.StudentID, cascadeDelete: true)
            .Index(t => t.CourseID)
            .Index(t => t.StudentID);
        
        CreateTable(
            "dbo.Student",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    LastName = c.String(),
                    FirstMidName = c.String(),
                    EnrollmentDate = c.DateTime(nullable: false),
                })
            .PrimaryKey(t => t.ID);
        
    }
    
    public override void Down()
    {
        DropForeignKey("dbo.Enrollment", "StudentID", "dbo.Student");
        DropForeignKey("dbo.Enrollment", "CourseID", "dbo.Course");
        DropIndex("dbo.Enrollment", new[] { "StudentID" });
        DropIndex("dbo.Enrollment", new[] { "CourseID" });
        DropTable("dbo.Student");
        DropTable("dbo.Enrollment");
        DropTable("dbo.Course");
    }
}

移行は、Up メソッドを呼び出して、移行のためのデータ モデルの変更を実装します。 更新をロールバックするためのコマンドを入力すると、移行が Down メソッドを呼び出します。

これは、コマンドを入力したときに作成された add-migration InitialCreate 初期移行です。 パラメーター (InitialCreate 例では) はファイル名に使用され、任意の名前にすることができます。通常は、移行で行われていることを要約した単語または語句を選択します。 たとえば、後で移行に "AddDepartmentTable" という名前を付ける可能性があります。

データベースが既に存在するときに、初期移行を作成した場合、データベースの作成コードが生成されますが、データベースは既にデータと一致しているため、作成コードを実行する必要はありません。 データベースがまだ存在しない別の環境にアプリを展開する場合、データベースを作成するために、このコードが実行されるため、最初にテストを行うことをお勧めします。 そのため、以前に接続文字列内のデータベースの名前を変更して、移行で新しいデータベースを最初から作成できるようにしました。

  1. [パッケージ マネージャー コンソール] ウィンドウで、次のコマンドを入力します。

    update-database

    コマンドは update-database 、 メソッドを Up 実行してデータベースを作成し、 メソッドを Seed 実行してデータベースにデータを設定します。 次のセクションに示すように、アプリケーションをデプロイした後、運用環境でも同じプロセスが自動的に実行されます。

  2. Server エクスプローラー を使用して、最初のチュートリアルで行ったようにデータベースを検査し、アプリケーションを実行して、すべてが以前と同じように動作することを確認します。

Azure にデプロイ

これまで、アプリケーションは開発用コンピューター上の IIS Express でローカルで実行されています。 他のユーザーがインターネット経由で使用できるようにするには、Web ホスティング プロバイダーに展開する必要があります。 チュートリアルのこのセクションでは、Azure にデプロイします。 このセクションは省略可能です。これをスキップして次のチュートリアルに進んだり、このセクションの手順を任意の別のホスティング プロバイダーに合わせて調整したりすることができます。

Code First の移行を使用してデータベースをデプロイする

データベースをデプロイするには、Code First Migrationsを使用します。 Visual Studio からデプロイするための設定を構成するために使用する発行プロファイルを作成するときに、[データベースの更新] というラベルのチェックボックスを選択します。 この設定により、Code First で初期化子クラスが使用されるように、展開プロセスによって、ターゲット サーバー上のアプリケーション Web.config ファイルが自動的に MigrateDatabaseToLatestVersion 構成されます。

Visual Studio は、プロジェクトをコピー先サーバーにコピーしている間、配置プロセス中にデータベースに対して何も行いません。 デプロイされたアプリケーションを実行し、デプロイ後に初めてデータベースにアクセスすると、Code First はデータベースがデータ モデルと一致するかどうかを確認します。 不一致がある場合、Code First はデータベースを自動的に作成するか (まだ存在しない場合)、データベース スキーマを最新バージョンに更新します (データベースが存在するが、モデルと一致しない場合)。 アプリケーションで Migrations Seed メソッドが実装されている場合は、データベースの作成後またはスキーマの更新後に メソッドが実行されます。

Migrations メソッドは Seed テスト データを挿入します。 運用環境にデプロイする場合は、 メソッドを変更 Seed して、運用データベースに挿入するデータのみを挿入する必要があります。 たとえば、現在のデータ モデルでは、実際のコースが必要ですが、開発データベースには架空の学生が必要な場合があります。 開発中に両方を Seed 読み込むメソッドを記述し、運用環境にデプロイする前に架空の学生をコメントアウトできます。 または、コースのみを読み込むメソッドを記述 Seed し、アプリケーションの UI を使用してテスト データベースに架空の学生を手動で入力することもできます。

Azure アカウントを取得する

Azure アカウントが必要です。 まだお持ちでないが、Visual Studio サブスクリプションをお持ちの場合は、 サブスクリプション特典をアクティブ化できます。 それ以外の場合は、わずか数分で無料試用版アカウントを作成できます。 詳細については、「Azure の無料試用版サイト」を参照してください。

Azure で Web サイトと SQL データベースを作成する

Azure の Web アプリは共有ホスティング環境で実行されます。つまり、他の Azure クライアントと共有されている仮想マシン (VM) で実行されます。 共有ホスティング環境は、クラウドで開始するための低コストの方法です。 その後、Web トラフィックが増加した場合、アプリケーションは専用 VM 上で実行することで、ニーズに合わせてスケーリングできます。 Azure App Serviceの価格オプションの詳細については、「App Service価格」を参照してください。

データベースを Azure SQL データベースにデプロイします。 SQL Database は、SQL Server テクノロジに基づいて構築されたクラウドベースのリレーショナル データベース サービスです。 SQL Serverで動作するツールとアプリケーションも SQL データベースと連携します。

  1. Azure 管理ポータルで、左側のタブで [リソースの作成] を選択し、[新しい] ウィンドウ (またはブレード) で [すべて表示] を選択して、使用可能なすべてのリソースを表示します。 [すべて] ブレードの [Web] セクションで [Webアプリ + SQL] を選択します。 最後に、[作成] を選択 します

    Azure portalでリソースを作成する

    新しい Web アプリ + SQL リソースを作成するためのフォームが開きます。

  2. [ アプリ名 ] ボックスに、アプリケーションの一意の URL として使用する文字列を入力します。 完全な URL は、ここで入力した内容と、Azure アプリ Services (.azurewebsites.net) の既定のドメインで構成されます。 アプリ名が既に取得されている場合、ウィザードから赤色の [アプリ名は使用できません] というメッセージが表示されます。 [アプリ名] が使用可能な場合は、緑色のチェックマークが表示されます。

  3. [サブスクリプション] ボックスで、App Serviceを配置する Azure サブスクリプションを選択します。

  4. [ リソース グループ ] テキスト ボックスで、リソース グループを選択するか、新しいリソース グループを作成します。 この設定では、Web サイトを実行するデータ センターを指定します。 リソース グループの詳細については、「リソース グループ」を参照してください。

  5. [App Service] セクション、[新規作成] をクリックして新しいApp Serviceプランを作成し、プランApp Service入力します (App Serviceと同じ名前)、場所および価格レベル (無料のオプションがあります)。

  6. [SQL Database] をクリックし、[新しいデータベースの作成] を選択するか、既存のデータベースを選択します。

  7. [ 名前 ] ボックスに、データベースの名前を入力します。

  8. [ ターゲット サーバー ] ボックスをクリックし、[ 新しいサーバーの作成] を選択します。 または、以前にサーバーを作成した場合は、使用可能なサーバーの一覧からそのサーバーを選択できます。

  9. [ 価格レベル ] セクションを選択し、[無料] を選択 します。 追加のリソースが必要な場合は、データベースをいつでもスケールアップできます。 Azure SQL価格の詳細については、「Azure SQL Database の価格」を参照してください。

  10. 必要に応じて照合順序を変更 します

  11. 管理者 SQL 管理ユーザー名SQL 管理 パスワードを入力します

    • [新しいSQL Database サーバー] を選択した場合は、後でデータベースにアクセスするときに使用する新しい名前とパスワードを定義します。
    • 前に作成したサーバーを選択した場合は、そのサーバーの資格情報を入力します。
  12. テレメトリ収集は、Application Insights を使用してApp Serviceに対して有効にすることができます。 構成が少ない Application Insights では、重要なイベント、例外、依存関係、要求、トレース情報が収集されます。 Application Insights の詳細については、「 Azure Monitor」を参照してください。

  13. 下部にある [ 作成 ] をクリックして、完了したことを示します。

    管理ポータルが [ダッシュボード] ページに戻り、ページ上部の [通知 ] 領域にサイトが作成されていることを示します。 しばらくすると (通常は 1 分未満)、デプロイが成功したことを示す通知が表示されます。 左側のナビゲーション バーの [App Services] セクションに新しいApp Serviceが表示され、新しい SQL データベースが [SQL データベース] セクションに表示されます。

Azure にアプリケーションをデプロイする

  1. Visual Studio のソリューション エクスプローラーで、プロジェクトを右クリックし、コンテキスト メニューの [発行] をクリックします。

  2. [発行先の選択] ページで、[App Service] を選択し、[既存] を選択して、[発行] を選択します。

    発行先ページを選択する

  3. Visual Studio で Azure サブスクリプションをまだ追加していない場合は、画面で手順を実行します。 これらの手順により、Visual Studio が Azure サブスクリプションに接続して 、App Services の一覧に Web サイトが含まれるようになります。

  4. [App Service] ページで、App Serviceを追加したサブスクリプションを選択します。 [ 表示] で、[ リソース グループ] を選択します。 App Serviceを追加したリソース グループを展開し、App Serviceを選択します。 [ OK] を 選択してアプリを発行します。

  5. 出力 ウィンドウでは、実行されたデプロイ操作が表示され、デプロイが問題なく完了したことが報告されます。

  6. デプロイが成功すると、既定のブラウザーが展開された Web サイトの URL に自動的に開きます。

    Students_index_page_with_paging

    これで、アプリはクラウドで実行されています。

この時点で、Azure SQL データベースに SchoolContext データベースが作成されました。これは、[Code First Migrationsの実行 (アプリの起動時に実行)] を選択したためです。 デプロイされた Web サイトの Web.config ファイルが変更され、 MigrateDatabaseToLatestVersion 初期化子は、コードがデータベース内のデータを初めて読み取りまたは書き込むときに実行されます ([ 学生 ] タブを選択したときに発生します)。

Web.config ファイルの抜粋

デプロイ プロセスでは、データベース スキーマの更新とデータベースのシード処理に使用するCode First Migrations用の新しい接続文字列 (SchoolContext_DatabasePublish) も作成されました。

Web.config ファイル内の接続文字列

Web.config ファイルの展開済みバージョンは、 ContosoUniversity\obj\Release\Package\PackageTmp\Web.configの自分 のコンピューターで確認できます。FTP を使用して、デプロイされた Web.config ファイル自体にアクセスできます。 手順については、「 Visual Studio を使用 ASP.NET Web 配置: コード更新プログラムをデプロイする」を参照してください。 「FTP ツールを使用するには、FTP URL、ユーザー名、パスワードの 3 つが必要です」で始まる手順に従います。

Note

Web アプリはセキュリティを実装していないため、URL を見つけたすべてのユーザーがデータを変更できます。 Web サイトをセキュリティで保護する方法については、「 Membership、OAuth、SQL データベースを使用してセキュリティで保護された ASP.NET MVC アプリを Azure にデプロイする」を参照してください。 Visual Studio の Azure 管理ポータルまたはサーバー エクスプローラーを使用してサービスを停止することで、他のユーザーがサイトを使用できないようにすることができます。

App Service のメニュー項目を停止する

高度な移行シナリオ

このチュートリアルに示すように移行を自動的に実行してデータベースを展開し、複数のサーバーで実行される Web サイトに展開する場合は、複数のサーバーが同時に移行を実行しようとする可能性があります。 移行はアトミックであるため、2 台のサーバーが同じ移行を実行しようとすると、1 台は成功し、もう 1 台は失敗します (操作を 2 回実行できない場合)。 これらの問題を回避する場合は、そのシナリオで移行を手動で呼び出し、1 回だけ発生するように独自のコードを設定できます。 詳細については、Rowan Miller のブログとMigrate.exe「コードからの移行の実行とスクリプト作成」を参照してください (コマンド ラインから移行を実行する場合)。

その他の移行シナリオの詳細については、「 Migrations Screencast Series」を参照してください。

特定の移行を更新する

update-database -target MigrationName

コマンドは update-database -target MigrationName 、対象となる移行を実行します。

データベースへの移行の変更を無視する

Add-migration MigrationName -ignoreChanges

ignoreChangesは、現在のモデルをスナップショットとして空の移行を作成します。

Code First 初期化子

デプロイ セクションで、 MigrateDatabaseToLatestVersion 初期化子が使用されているのを確認しました。 Code First には、 CreateDatabaseIfNotExists (既定値)、 DropCreateDatabaseIfModelChanges (前に使用した) や DropCreateDatabaseAlways など、他の初期化子も用意されています。 初期化子は DropCreateAlways 、単体テストの条件を設定するのに役立ちます。 独自の初期化子を記述することもできます。また、アプリケーションがデータベースから読み取りまたはデータベースへの書き込みを行うまで待機しない場合は、初期化子を明示的に呼び出すことができます。

初期化子の詳細については、「 Entity Framework Code First のデータベース初期化子 について」および「 Programming Entity Framework: Code First by Julie Lerman and Rowan Miller」の第 6 章を参照してください。

コードを取得する

完成したプロジェクトをダウンロードする

その他のリソース

他の Entity Framework リソースへのリンクは、「 ASP.NET データ アクセス - 推奨リソース」にあります

次の手順

このチュートリアルでは、次の作業を行いました。

  • 有効なコードの最初の移行
  • Azure にアプリをデプロイしました (省略可能)

次の記事に進み、ASP.NET MVC アプリケーションのより複雑なデータ モデルを作成する方法について説明します。