Skip to main content
評価してください: 

このビデオおよびチュートリアルでは、新しいデータベースを対象とした Code First 開発の概要について説明します。このシナリオでは、対象となるデータベースがまだ存在せず Code First によって作成する場合や、Code First によって空のデータベースに新しいテーブルを追加する場合を扱います。Code First では、C# または VB.Net のクラス使用してモデルを定義することができます。追加の構成は、クラスやプロパティの属性を使用するか Fluent API を使用して、必要に応じて実行できます。

( ビデオ選択 - ダウンロードを含む (英語))

 

必要条件

このチュートリアルを完了するには、Visual Studio 2010 または Visual Studio 2012 がインストールされている必要があります。

Visual Studio 2010 を使用している場合、 NuGet (英語) もインストールする必要があります。

 

1.アプリケーションの作成

作業を簡単にするために、Code First を使用してデータ アクセスを実行する基本的なコンソール アプリケーションを作成します。

  • Visual Studio を開きます。
  • [ファイル] -> [新規作成] -> [プロジェクト] の順にクリックします。
  • 左側のメニューの [Windows] から [コンソール アプリケーション] をクリックします。
  • 名前として「CodeFirstNewDatabaseSample」を入力します
  • [OK] をクリックします。

 

2.モデルの作成

クラスを使用して簡単なモデルを定義します。このモデルは Program.cs ファイルに定義していますが、実際のアプリケーションでは、クラスを個別のファイルに分割したり、場合によっては個別のプロジェクトに分割することがあります。

Program.cs の Program クラス定義の下に、次の 2 つのクラスを追加します。

public class Blog
{
    public int BlogId { get; set; }
    public string Name { get; set; }

    public virtual List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogId { get; set; }
    public virtual Blog Blog { get; set; }
}

ここでは、2 つのナビゲーション プロパティ (Blog.Posts と Post.Blog) を仮想プロパティにしています。これにより、Entity Framework の遅延読み込み機能が有効になります。遅延読み込みを使用すると、これらのプロパティにアクセスしたとき、プロパティの内容がデータベースから自動的に読み込まれます。

 

3.コンテキストの作成

次に、データベースとのセッションを表す派生コンテキストを定義します。このコンテキストによって、クエリの実行とデータの保存が可能になります。ここでは System.Data.Entity.DbContext から派生し、モデル内にある各クラスの型指定された DbSet<TEntity> を公開するコンテキストを定義します。

Entity Framework から型の使用を開始するので、EntityFramework NuGet パッケージを追加する必要があります。

  • [プロジェクト] –> [NuGet パッケージの管理] をクリックします。
    メモ: [NuGet パッケージの管理] オプションが使用できない場合、 NuGet の最新バージョン (英語)をインストールする必要があります。
  • [オンライン] タブをクリックします。
  • [EntityFramework] パッケージをクリックします。
  • [インストール] をクリックします。

Program.cs の最上部に System.Data.Entity に対する using ステートメントを追加します。

using System.Data.Entity;

Program.cs の Post クラスの下に、次の派生コンテキストを追加します。

public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
}

Program.cs に含まれるすべての内容を次に示します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;

namespace CodeFirstNewDatabaseSample
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }

    public class Blog
    {
        public int BlogId { get; set; }
        public string Name { get; set; }

        public virtual List<Post> Posts { get; set; }
    }

    public class Post
    {
        public int PostId { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }

        public int BlogId { get; set; }
        public virtual Blog Blog { get; set; }
    }

    public class BloggingContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }
    }
}

上に示したものが、データの格納と取得を開始するために必要となるすべてのコードです。背景ではさまざまな処理が行われており、短い時間でその処理を見ていきますが、最初にコードの実行を取り上げます。

 

4.データの読み取りと書き込み

次に示すように、Program.cs の Main メソッドを実装します。このコードは、コンテキストの新しいインスタンスを作成し、そのインスタンスを使用して新しいブログを挿入します。次に、LINQ クエリを使用して、データベースからすべてのブログをタイトルのアルファベット順に取得します。

class Program
{
    static void Main(string[] args)
    {
        using (var db = new BloggingContext())
        {
            // Create and save a new Blog
            Console.Write("Enter a name for a new Blog: ");
            var name = Console.ReadLine();

            var blog = new Blog { Name = name };
            db.Blogs.Add(blog);
            db.SaveChanges();

            // Display all Blogs from the database
            var query = from b in db.Blogs
                        orderby b.Name
                        select b;

            Console.WriteLine("All blogs in the database:");
            foreach (var item in query)
            {
                Console.WriteLine(item.Name);
            }

            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }
    }
}

ここで、アプリケーションを実行してテストします。

Enter a name for a new Blog: ADO.NET Blog
All blogs in the database:
ADO.NET Blog
Press any key to exit...

 

データの場所

規約に従い、DbContext はデータベースを自動的に作成しました。

  • ローカルの SQL Express インスタンスを使用できる場合 (Visual Studio 2010 では既定でインストールされます)、Code First ではそのインスタンス上にデータベースが作成されます。
  • SQL Express を使用できない場合、Code First では LocalDb (Visual Studio 2012 で既定でインストールされます) の使用を試みます。
  • データベースの名前は派生コンテキストの完全修飾名に従って設定されます。この場合は、CodeFirstNewDatabaseSample.BloggingContext になります。

以上は既定の規約であり、Code First で使用されるデータベースを変更するにはさまざまな方法があります。詳細については、「DbContext でモデルとデータベースの接続を検出する方法」 のトピックを参照してください。

 

Visual Studio のサーバー エクスプローラーを使用して、このデータベースに接続できます。

  • [表示] -> [サーバー エクスプローラー] をクリックします。
  • [データ接続] を右クリックし、[接続の追加] をクリックします。
  • サーバー エクスプローラーからデータベースにまだ接続していない場合は、データ ソースとして Microsoft SQL Server を選択する必要があります。
    データ ソースとして選択された Microsoft SQL Server
  • インストールされているツールに応じて、LocalDb ((localdb)\v11.0) または SQL Express (.\SQLEXPRESS) のどちらかに接続します。
    (localdb)\v11.0 での Blogging データベースへの接続.\SQLEXPRESS での Blogging データベースへの接続

 

これで、Code First が作成したスキーマを検査できます。

サーバー エクスプローラーに表示されるスキーマ

DbContext では、定義した DbSet のプロパティを調べることによって、どのクラスをモデルに含めるかを判別しました。次に、Code First 規約の既定のセットを使用して、テーブルと列の名前の特定、データ型の特定、主キーの検索などを実行します。このチュートリアルの後半では、これらの規約をオーバーライドする方法について説明します。

 

5.モデルの変更の処理

次に、モデルに変更を加えます。変更を加えた場合は、データベース スキーマを更新する必要があります。これを行うには、Code First Migrations 機能 (単に Migrations と呼ばれる場合もあります) を使用します。

Migrations を使用すると、順序が指定された一連の手順を利用して、データベース スキーマのアップグレード (およびダウンロード) を実行できます。移行と呼ばれるこれらの各手順には、適用される変更内容を記述したコードが含まれています。 

最初の手順では、BloggingContext に対して Code First Migrations を有効にします。

  • [ツール] -> [ライブラリ パッケージ マネージャー] -> [パッケージ マネージャー コンソール] の順にクリックします。
  • パッケージ マネージャー コンソールで、Enable-Migrations コマンドを実行します。
  • 次の 2 つの項目を含む新しい Migrations フォルダーがプロジェクトに追加されます。
    • Configuration.cs - このファイルには BloggingContext を移行するために Migrations で使用される設定が含まれています。このチュートリアルではこの設定を変更する必要はありませんが、このファイルでは、シード データの指定、他のデータベースのプロバイダーの登録、移行が生成される名前空間の変更などを行うことができます。
    • <タイムスタンプ>_InitialCreate.cs – ここで行うのは最初の移行です。このファイルはデータベースに対して既に適用された変更内容を表します。ここでは、空のデータベースが Blogs テーブルと Posts テーブルを含んだデータベースになった状況が表されます。これらのテーブルは Code First によって自動的に作成されますが、ここでは Migrations を選択しているので、これらのテーブルは Migration に変換されます。Code First の記録はローカル データベース内で行われます。この Migration は既に適用されています。ファイル名のタイムスタンプは、順序を指定するために使用されます。

    次に、モデルに変更を加え、Blog クラスに URL プロパティを追加します。
public class Blog
{
    public int BlogId { get; set; }
    public string Name { get; set; }
    public string Url { get; set; }
    public virtual List<Post> Posts { get; set; }
}
  • パッケージ マネージャー コンソールで、Add-Migration AddUrl コマンドを実行します。

    Add-Migration コマンドは、前回の移行の後で加えられた変更内容を調べ、検索された変更内容を使用して新しい移行をスキャフォールディングします。移行に名前を付けることができます。この場合、「AddUrl」という名前を付けます。

    スキャフォールディングされたコードでは、dbo.Blogs テーブルに Url 列を追加する必要があります。この列には文字列データが保存されます。必要に応じてスキャフォールディングされたコードを編集できますが、この場合は編集する必要はありません。

namespace CodeFirstNewDatabaseSample.Migrations
{
    using System;
    using System.Data.Entity.Migrations;
    
    public partial class AddUrl : DbMigration
    {
        public override void Up()
        {
            AddColumn("dbo.Blogs", "Url", c => c.String());
        }
        
        public override void Down()
        {
            DropColumn("dbo.Blogs", "Url");
        }
    }
}
  • パッケージ マネージャー コンソールで、Update-Database コマンドを実行します。このコマンドは、保留中の移行をデータベースに適用します。InitialCreate 移行は既に適用されているため、Migrations では新しい AddUrl 移行だけが適用されます。

    ヒント: Update-Database を呼び出すときに、–Verbose スイッチを使用して、データベースに対して実行されている SQL を確認できます。

 

新しい Url 列がデータベース内の Blogs テーブルに追加されています。

サーバー エクスプローラーに表示されるスキーマ 

6.データ注釈

ここまでは、EF を使用して既定の規約を使用しているモデルを検出しましたが、場合によっては、クラスが規約に従っていないために、より詳細な構成を実行できるようにする必要があります。そのためには 2 つの方法があります。このセクションではデータ注釈について説明し、次のセクションでは Fluent API について説明します。

  • モデルに User クラスを追加します。
public class User
{
    public string Username { get; set; }
    public string DisplayName { get; set; }
}
  • 派生コンテキストに次の設定を追加する必要もあります。
public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
    public DbSet<User> Users { get; set; }
}
  • 移行を追加しようとしたときに、「EntityType 'User' にはキーが定義されていません。この EntityType にはキーを定義してください。」というエラーが発生しました。これは、EF は Username が User の主キーであることを認識する方法を備えていないためです。
  • ここで、データ注釈を使用します。Program.cs の上部に using ステートメントを追加する必要があります。
using System.ComponentModel.DataAnnotations;
  • 次に、Username プロパティに注釈を付けて、主キーであることを指定します。
public class User
{
    [Key]
    public string Username { get; set; }
    public string DisplayName { get; set; }
}
  • Add-Migration AddUser コマンドを使用して、移行をスキャフォールディングし、これらの変更をデータベースに適用します。
  • Update-Database コマンドを実行して、新しい移行をデータベースに適用します。

新しいテーブルがデータベースに追加されました。

サーバー エクスプローラーに表示されるスキーマ

 

EF でサポートされる注釈の完全な一覧は次のとおりです。

 

7.Fluent API

前のセクションでは、データ注釈を使用して、規約によって検出されたデータを補完またはオーバーライドしました。モデルを構成するもう一つの方法として、Code First Fluent API を使用する方法があります。

ほとんどのモデル構成は、簡単なデータ注釈を使用して実行できます。Fluent API は高度な方法です。データ注釈で処理できるすべてのデータに加えて、データ注釈では対応できない高度な構成も対象とするモデル構成を指定できます。データ注釈と Fluent API は一緒に使用できます。

Fluent API にアクセスするには、DbContext の OnModelCreating をオーバーライドします。たとえば、User.DisplayName が格納される列の名前を display_name に変更するとします。

  • 次のコードを使用して、BloggingContext の OnModelCreating メソッドをオーバーライドします。
public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
    public DbSet<User> Users { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>()
            .Property(u => u.DisplayName)
            .HasColumnName("display_name");
    }
}
  • Add-Migration ChangeDisplayName コマンドを使用して、移行をスキャフォールディングし、これらの変更をデータベースに適用します。
  • Update-Database コマンドを実行して、新しい移行をデータベースに適用します。

 

DisplayName 列の名前が display_name に名前に変更されています。

サーバー エクスプローラーに表示されるスキーマ

まとめ

このチュートリアルでは、新しいデータベースを使用した Code First 開発を取り上げました。ここでは、クラスを使用してモデルを定義し、そのモデルを使用してデータベースを作成し、データの格納と取得を行いました。データベースの作成後に、Code First Migrations を使用し、モデルの変化に合わせてスキーマを変更しました。また、データ注釈と Fluent API を使用したモデルの構成方法も確認しました。

ページのトップへ