Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

執筆時点の環境

  • 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パッケージを入れる

参考資料

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした