執筆時点の環境
- 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メソッド先頭に以下の記述を追加
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を作成。
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・テーブルの生成を行う。
PS> Add-Migration 適当な名前
PS> Update-Database
プロジェクトの/Migrations/下に"適当な名前"のMigration派生クラスが生成される。このクラスの内容が実行されることでDB操作が行われる。上のコマンドではAdd-Migrationで派生クラス生成、Update-Databaseで生成クラスを元にDB操作が行われている。
DB生成を間違えた時は、下記操作を行うとやり直し可能。
- プロジェクトへ追加された"Migrations"フォルダを削除
- パッケージマネージャコンソールからDrop-Databaseを実行
Mainメソッドで使ってみる
DBの準備は完了。実際にDBを使用してみる。MainメソッドにDBを使用するコードを記述する。
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テーブルが更新されている事を確認できれば成功。
その他の操作
エンティティクラスのメンバを編集したい時
エンティティクラスへメンバを編集後、「パッケージマネージャ コンソール」から以下のコマンドを叩く
PS> Add-Migration 加えた変更が分かる名称
PS> Update-Database
直前の編集を取り消したい時 (DBアップデート前)
以下のコマンドを叩く。DBアップデート後だった場合には取消しマイグレーションとして上の追加時の操作を行う。
PS> Remove-Migration
DBを消したい時
以下のコマンドを叩く。叩いた後にプロジェクトのMigrationsフォルダを削除
PS> Drop-Database
おまけ
使用DBをSQLiteに切替えてみる
NuGetから必要パッケージをインスール
- Microsoft.EntityFrameworkCore.Sqlite
AppDbContextを書き換える
これまではMicrosoft.EntityFrameworkCore.SqlServerの外部拡張メソッドによってSQL Serverを使用するよう設定されていました。Sqlite用を使用するよう書き換えてみます。
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を作成する
PS> Update-Database
CLI版を使ってみる
こっちの方が好み。
# 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"に書き換える必要があります。
<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パッケージを入れる
参考資料
- Entity Framework Core
https://docs.efproject.net/en/latest/index.html - .NET Core での コンソールアプリの文字化けを直す
http://aquasoftware.net/blog/?p=895