vaguely

和歌山に戻りました。ふらふらと色々なものに手を出す毎日。

Entity Framework Core のスキャフォールド・マイグレーションで生成されたものを見たい

はじめに

前回、半年間溜め込んでいた内容をようやくブログとして書くことができて、スッキリしている今日この頃ですw

今回は生成されたファイルを覗いてみることにします。

マイグレーションはスキャフォールドを必要とするか

前回はスキャフォールドで View 、 Controller を生成したあとマイグレーションを実行していました。

ただ、 Controller はともかく View は不要( Web API とか)な場合、わざわざスキャフォールドしなくても Controller だけ作れば良いような気もします。

ということで確認したところ、特にスキャフォールドを実行していなくてもマイグレーションできました。

ということで、状況に合わせて使い分けるのが良さそうですね。

生成した・されたファイルを見てみる

さて、前回 Empty テンプレートの ASP.NET Core プロジェクトに追加した、またはスキャフォールド・マイグレーションで生成されたファイルを見てみることにします。

Controllers
  L MoviesController.cs
Migrations
  L 20190214222750_AddMovie.cs
  L 20190214222750_AddMovie.Designer.cs
  L EfCoreSampleContextModelSnapshot.cs
Models
  L EfCoreSampleContext.cs
  L Movie.cs
Views
  L Movies
    L Create.cshtml
    L Delete.cshtml
    L Details.cshtml
    L Edit.cshtml
    L Index.cshtml
  L Shared
    L _ValidationScriptsPartial.cshtml

View の部分は基本的に Razor で Form を出しているだけなのでスキップすることにして、それ以外の部分を追いかけてみたいと思います。

Movie.cs を見る

C# 側でデータを保持し、マイグレーション時に DB のテーブル生成するのにも使われるクラスです。

Movie.cs

using System;
using System.ComponentModel.DataAnnotations;

namespace EfCoreSample.Models
{
    public class Movie
    {
        public int MovieId { get; set; }
        public string Title { get; set; }

        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; }
        public decimal Price { get; set; }
    }
}

DataType

ただデータを保持するクラス、ということで、そんなに変わったところも見られません。

唯一気になるのが「[DataType(DataType.Date)]」の属性。

↑などを見ると、どうやら Razor で下記のようなフォームを表示するのに使われているようです。

f:id:mslGt:20190219063847p:plain

試しにコメントアウトしてみると、他と同じようにただ入力エリアが表示されていました。

DB 側に関係があるかはよく分かっていませんが。

EfCoreSampleContext.cs を見る

次は EfCoreSampleContext.cs です。

Entity Framework Core in Action によると DB へのアクセスや設定を担う、ということで、今回の中で一番重要なクラスと言えそうです。

EfCoreSampleContext.cs

using Microsoft.EntityFrameworkCore;

namespace EfCoreSample2.Models
{
    public class MovieContext : DbContext
    {
        public MovieContext (DbContextOptions< MovieContext> options) : base(options)
        {
        }

        public DbSet< Movie> Movie { get; set; }
    }
}

この中に含まれるキーワードとしては下記の 3 つがあります。

  1. DbContext
  2. DbContextOptions
  3. DbSet

DbContext Class (Microsoft.EntityFrameworkCore) などを見ると、 DB との直接的なやり取りをしているのは DbContext クラスとのこと。

2.の DbContextOptions は、接続する DB の情報などを渡すのに使われるようです。

https://github.com/JonPSmith/EfCoreInAction/blob/Chapter01/MyFirstEfCoreApp/AppDbContext.cs

(関係ないですが、ブランチを本の章を切り替えるのに使うのが新鮮というか、ちょっとびっくりしました)

これをどこから渡しているかというと、 Startup > ConfigureServices() です。

Startup.cs

~省略~
public void ConfigureServices(IServiceCollection services)
{
    services.Configure< CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddDbContext< EfCoreSampleContext>(options =>
        options.UseSqlite(Configuration.GetConnectionString("MovieContext")));

    services.AddMvc();
}
~省略~

SQLite の使用と Data Source として MvcMovie.db が指定されています。

appsettings.json

~省略~
  "ConnectionStrings": {
    "MovieContext": "Data Source=MvcMovie.db"
  }
}

3.の DbSet は、 DbContext の Set() で Entity クラスとして登録するのに使われるようです。

また、スキャフォールドで生成された MoviesController.cs を見てみると、 DB アクセスの部分は MovieContext(DbContext) 、または DbSet を検索したり、値を取得しているだけのようです。

MoviesController.cs

~省略~
[Route("/Movies/Details/{*id}")]
public async Task< IActionResult> Details(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie
        .FirstOrDefaultAsync(m => m.MovieId == id);
    if (movie == null)
    {
        return NotFound();
    }

    return View(movie);
}
~省略~
[HttpPost]
[Route("/Movies/Create")]
[ValidateAntiForgeryToken]
public async Task< IActionResult> Create([Bind("MovieId,Title,ReleaseDate,Genre,Price")] Movie movie)
{
    if (ModelState.IsValid)
    {

        _context.Add(movie);
        await _context.SaveChangesAsync();

        return RedirectToAction(nameof(Index));
    }
    return View(movie);
}
~省略~

ということを考えると、 Entity Framework Core がどんなことをしてくれるのかを知るためには DbContext を中心に調べていくのが良さそうです。

処理を調べるにはドキュメントとコードを見るのが一番、だと思いますが、 Entity Framework Core のコードは下記にあります。

その中の DbContext はこちら。

https://github.com/aspnet/EntityFrameworkCore/blob/master/src/EFCore/DbContext.cs

次回はこれをたどってみることにします。

参照