次の方法で共有


新しいデータベースへの最初のコード

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

ビデオを見る

このビデオでは、新しいデータベースをターゲットとする Code First 開発の概要について説明します。 このシナリオには、存在しないデータベースと Code First によって作成されるデータベース、または Code First が新しいテーブルを追加する空のデータベースをターゲットにすることが含まれます。 Code First では、C# クラスまたは VB.Net クラスを使用してモデルを定義できます。 必要に応じて、クラスとプロパティの属性を使用するか、fluent API を使用して、追加の構成を実行できます。

発表者: ローワン・ミラー

ビデオ: WMV | MP4 | WMV (ZIP)

前提条件

このチュートリアルを完了するには、少なくとも 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 パッケージを追加する必要があります。

  • Project –> 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 を選択する必要があります。

    データ ソースの選択

  • インストールした LocalDB または SQL Express のいずれかに接続する

Code First によって作成されたスキーマを調べることができるようになりました。

スキーマ初期化

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

5. モデルの変更に対処する

次に、モデルにいくつかの変更を加えます。これらの変更を行うときは、データベース スキーマも更新する必要があります。 これを行うには、Code First Migrations と呼ばれる機能、または短く「移行」を使用します。

移行により、データベース スキーマをアップグレード (およびダウングレード) する方法を説明する一連の手順を順序付けすることができます。 移行と呼ばれるこれらの各手順には、適用する変更を記述するコードが含まれています。 

最初の手順は、BloggingContext の Code First Migrations を有効にすることです。

  • ツール -> ライブラリ パッケージ マネージャー -> パッケージ マネージャー コンソール

  • パッケージ マネージャー コンソール で Enable-Migrations コマンドを実行する

  • 次の 2 つの項目を含む新しい Migrations フォルダーがプロジェクトに追加されました。

    • Configuration.cs – このファイルには、移行が BloggingContext の移行に使用する設定が含まれています。 このチュートリアルでは何も変更する必要はありませんが、ここではシード データの指定、他のデータベースのプロバイダーの登録、移行が生成される名前空間の変更などを行うことができます。
    • <timestamp>_InitialCreate.cs – これは、データベースに既に適用されている変更を表し、空のデータベースからブログと投稿テーブルを含むデータベースに移行します。 Code First ではこれらのテーブルを自動的に作成しましたが、マイグレーションにオプトインしたため、それらはマイグレーションとして変換されました。 Code First は、この移行が既に適用されていることをローカル データベースにも記録しています。 ファイル名のタイムスタンプは、順序付けのために使用されます。

    次に、モデルに変更を加え、ブログ クラスに 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' を呼び出します。 スキャフォールディングされたコードは、文字列データを保持できる URL 列を dbo.Blogs の表に追加する必要があることを示しています。 必要に応じて、スキャフォールディングされたコードを編集できますが、この場合は必要ありません。
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 の移行は既に適用されているため、移行では新しい AddUrl 移行が適用されます。 ヒント: Update-Database を呼び出すときに –Verbose スイッチを使用して、データベースに対して実行されている SQL を確認できます。

これで、新しい URL 列がデータベースの Blogs テーブルに追加されました。

URL を含むスキーマ

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にはユーザー名が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

前のセクションでは、データ注釈を使用して、規則によって検出されたものを補完またはオーバーライドする方法について説明しました。 モデルを構成するもう 1 つの方法は、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 を使用してモデルを構成する方法についても説明しました。