Edited at

EntityFrameworkCoreを.NET Core コンソールアプリでCodeFirstに使う


執筆時点の環境


  • Windows 10 を使用

  • VisualStudio Community 2017 (略称 VS) インストール済み

  • Microsoft SQL Server Data Tools インストール済み (VSのインストーラに付随)

  • .NET Core 1.0.4

  • EntityFrameworkCore 1.1.2


CodeFirstとは

ソースコードを先に書き、それを元にEntityFrameworkにDB・テーブルを生成させるようなスタイル。ルールに則ってコード記述を行うことでDBやテーブルの生成はフレームワーク側が行ってくれる。

基本ルール


  • エンティティクラス:

    扱うデータを表現するクラス。DBのレコードと対応する。何も継承する必要は無く、カラムと対応するプロパティを持つ。

  • コンテキストクラス:

    DbContextを継承させる。管理するエンティティクラスをDbSet<T>型のプロパティとして保持させる。レコード取得やレコード保存はこのクラスのインスタンスを通して行う。


使ってみる


VisualStudio でプロジェクト作成

テンプレート「.NET Core」-「Console Application (.NET Core)」でプロジェクト作成

(プロジェクト名はHelloCoreとする)

コンソールに日本語を出力すると文字化けする。

.NET Coreは標準ではUnicode, ASCII, CodePage 28591 以外に対応していない一方、WindowsのコンソールはShift-JISである事が原因。NuGet経由でShift-JISへ対応させるパッケージを導入すれば日本語表示可能。以下の作業で対応させる。

NuGetからパッケージ「System.Text.Encoding.CodePages」をインスール

Mainメソッド先頭に以下の記述を追加


Program.cs


public static void Main(string[] args)
{
+ //登録すれば必要な場面(Win上で実行した時)で使用されます。
+ System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);


EntityFrameworkCoreを使う

SQL Serverと組合せ、指定したフィードから記事タイトルと抜粋を取得しDBへ保存するアプリを作成する。


NuGetで必要パッケージをインストール。


  • Microsoft.EntityFrameworkCore

  • Microsoft.EntityFrameworkCore.Design

  • Microsoft.EntityFrameworkCore.SqlServer

  • Microsoft.EntityFrameworkCore.Tools


エンティティクラスを作成

データの受け皿となるクラスとしてArticle, AppDbContextを作成。


Program.cs

using System;

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace HelloCore
{
public class Program
{
public static void Main(string[] args)
{
//登録すれば必要な場面(Win上で実行した時)で使用される。
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
}
}
//エンティティクラス
public class Article
{
public int Id { get; set; }
public string LinkUrl { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string ChannelTitle { get; set; }
}
//コンテキストクラス
public class AppDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
//ここでは接続先のDB名はhellocoredbとする
optionsBuilder.UseSqlServer(@"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=hellocoredb;");
}
public DbSet<Article> Article { get; set; }
}
}


VS上で「パッケージマネージャ コンソール」を開く。

コンソールはMicrosoft.EntityFrameworkCore.Toolsによって追加されたコマンドが使用可能になっています。

これを用いてAppDbContextクラスが宣言したDB・テーブルの生成を行う。


PackageManagerConsole

PS> Add-Migration 適当な名前

PS> Update-Database

プロジェクトの/Migrations/下に"適当な名前"のMigration派生クラスが生成される。このクラスの内容が実行されることでDB操作が行われる。上のコマンドではAdd-Migrationで派生クラス生成、Update-Databaseで生成クラスを元にDB操作が行われている。

DB生成を間違えた時は、下記操作を行うとやり直し可能。


  1. プロジェクトへ追加された"Migrations"フォルダを削除

  2. パッケージマネージャコンソールからDrop-Databaseを実行


Mainメソッドで使ってみる

DBの準備は完了。実際にDBを使用してみる。MainメソッドにDBを使用するコードを記述する。


Program.cs

using System;

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace HelloCore
{
public class Program
{
public static void Main(string[] args)
{
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
Console.WriteLine("開始");

var db = new AppDbContext();
var http = new System.Net.Http.HttpClient();

//フィードを適当なサイトから取得
foreach (var targetUrl in
new[] {
"http://www3.asahi.com/rss/index.rdf",
"http://rss.rssad.jp/rss/codezine/new/20/index.xml",
})
{
//フィードxmlをDL & Parse
//xmlは名前空間で面倒が生じないよう名前空間情報を除染
var rssTxt = http.GetStringAsync(targetUrl).Result;
var rss = System.Xml.Linq.XElement.Parse(rssTxt);
foreach (var item in rss.Descendants())
item.Name = item.Name.LocalName;

//フィードの記事をModelオブジェクトへ移し替える
var articles = rss
.Descendants("item")
.Select(item =>
new Article()
{
Title = item.Element("title").Value,
LinkUrl = item.Element("link").Value,
Description = item.Element("description").Value,
ChannelTitle = rss.Element("channel").Element("title").Value,
});

//DBに未追加の記事をDBへ保存する
foreach (var item in articles)
{
if (db.Article.Any(_ => _.LinkUrl == item.LinkUrl))
continue;

Console.WriteLine(item.Title);
db.Article.Add(item);
}
}
//DBへの保存を確定
db.SaveChanges();
Console.WriteLine("終了");
Console.Read();
}
}
//エンティティクラス
public class Article
{
public int Id { get; set; }
public string LinkUrl { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string ChannelTitle { get; set; }
}
//コンテキストクラス
public class AppDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
//ここでは接続先のDB名はhellocoredbとする
optionsBuilder.UseSqlServer(@"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=hellocoredb;");
}
public DbSet<Article> Article { get; set; }
}
}


VisualStudioで実行。

フィードがコンソールに表示され、VSの「SQL Server オブジェクト エクスプローラ」からhellocoredbのArticleテーブルが更新されている事を確認できれば成功。


その他の操作


エンティティクラスのメンバを編集したい時

エンティティクラスへメンバを編集後、「パッケージマネージャ コンソール」から以下のコマンドを叩く


PackageManagerConsole

PS> Add-Migration 加えた変更が分かる名称

PS> Update-Database


直前の編集を取り消したい時 (DBアップデート前)

以下のコマンドを叩く。DBアップデート後だった場合には取消しマイグレーションとして上の追加時の操作を行う。


PackageManagerConsole

PS> Remove-Migration



DBを消したい時

以下のコマンドを叩く。叩いた後にプロジェクトのMigrationsフォルダを削除


PackageManagerConsole

PS> Drop-Database



おまけ


使用DBをSQLiteに切替えてみる


NuGetから必要パッケージをインスール


  • Microsoft.EntityFrameworkCore.Sqlite


AppDbContextを書き換える

これまではMicrosoft.EntityFrameworkCore.SqlServerの外部拡張メソッドによってSQL Serverを使用するよう設定されていました。Sqlite用を使用するよう書き換えてみます。


Program.cs

public class AppDbContext : DbContext

{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
//ここでは接続先のDB名はhellocoredbとする
- optionsBuilder.UseSqlServer(@"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=hellocoredb;");
+ optionsBuilder.UseSqlite(@"Data Source='hello.db'");
}
public DbSet<Article> Article { get; set; }
}


SQLiteでDBを作成する


PackageManagerConsole

PS> Update-Database



CLI版を使ってみる

こっちの方が好み。


cmd

# CLI版を使う際には追加パッケージをインストールします。

dotnet add package Microsoft.EntityFrameworkCore.Tools.DotNet

# Add-Migration 適当な名前
dotnet ef migrations add 適当な名前

# Remove-Migration
dotnet ef migrations remove

# Update-Database
dotnet ef database update

# Drop-Database
dotnet ef database drop


追加パッケージインストール後には.csprojを開いて入れたパッケージの参照タグの名前を"PackageReference"から"DotNetCliToolReference"に書き換える必要があります。


HelloCore.csproj

    <PackageReference Include="System.Text.Encoding.CodePages" Version="4.3.0" />

- <PackageReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.1" />
+ <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.1" />
</ItemGroup>
</Project>


まとめ


  • 規約を守った記述を行っていればDB構築はコマンド一本

  • EntityFrameworkCore + SQL Serverで最低限必要なパッケージは無印, Design, SqlServer, Tools

  • SQLiteも公式対応。SqlServerの代わりにSqliteパッケージを入れる


参考資料