SQLITEをEntityFrameworkで使う

# SQLITEをEntityFrameworkで使う
簡単なクライアントアプリを作ろうと思うと、わざわざDBサーバを立てるのは面倒くさい。でもDBを扱いたい時が出てくると思います。
今回は前から気になっていたSQLITEを使って、DBサーバーなしでRDMBSを扱ってみたいと思います。

## ライブラリの導入

ソリューションエクスプローラの「参照」を右クリックし、「Nget パッケージの管理」をクリックする。
![01.png](https://qiita-image-store.s3.amazonaws.com/0/143896/abbad127-4a72-d58a-2672-bdc707703796.png)

「Microsoft.EntityFrameworkCore.sqlite」で検索をかけて、インストールする。
投稿時は2.0.1が安定板でしたので、それを入れました。
途中で同意メッセージが表示されるので、同意しましょう。
![02.png](https://qiita-image-store.s3.amazonaws.com/0/143896/a59220fd-b1f2-e68b-a7ec-11c71168463b.png)

同じ要領で「Microsoft.EntityFrameworkCore.tools」もインストールします。

## エンティティクラスの作成

テーブル定義をするノリで、Entityを作成します。
今回は「Entity」というフォルダを作成し、その中に「Item」というエンティティクラスを追加しました。

```csharp:Item.cs
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace EntranceAndExitRecord.Entity
{
    [Table("Item")]
    public class Item
    {
        [Key]
        [Required]
        public int PointNo { set; get; }

        [Key]
        [Required]
        public int Id { set; get; }

        [Required]
        public string ItemName { set; get; }

        [Required]
        public int SortNum { set; get; }
    }
}
```

## モデルの作成

```csharp:EntranceAndExitRecord.cs
using EntranceAndExitRecord.Entity;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;

namespace EntranceAndExitRecord.Model
{
    public class EntranceAndExitRecordModel : DbContext
    {
        public DbSet<Item> Items { get; internal set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            var connectionString = new SqliteConnectionStringBuilder { DataSource = @"C:\work\EntranceAndExitRecord.db" }.ToString();
            optionsBuilder.UseSqlite(new SqliteConnection(connectionString));
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            // 複合キーの場合、以下のように指定してやる。
            // ない場合「Entity type 'Item' has composite primary key defined with data annotations. To set composite primary key, use fluent API.」と表示される
            modelBuilder.Entity<Item>().HasKey(c => new { c.Id, c.PointNo });
        }
    }
}
```

## マイグレーションの実施

クラスファイルからsqliteのファイルを生成します。
パッケージマネージャーコンソールから、以下のコマンドを実行します。
実行するとEntranceAndExitRecordModel#OnConfiguring()で指定した場所に.dbファイルができます。

```
Enable-Migrations
Add-Migration EntranceAndExitRecord
Update-Database
```

試しに.dbファイルを開いてみたいと思います。
私は[DB Browser for SQLite](http://sqlitebrowser.org/)を使わせていただきました。
![03.png](https://qiita-image-store.s3.amazonaws.com/0/143896/1998a18e-829c-4196-9f6e-3041889e1b22.png)
ちゃんとItemテーブルができてます。

## 入力ページの作成

とりあえずなのでItemテーブルに入力するためのページを作ってみます。
（とりあえずでだいぶ雑です・・。本来はMVVMを意識してやるべきですが、とりあえず動確ということで。）

```xml:ItemInput.xaml
<Page x:Class="EntranceAndExitRecord.Views.ItemInput"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:EntranceAndExitRecord.Views"
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"
      Title="ItemInput">

    <Grid>
        <Label Content="拠点ID" HorizontalAlignment="Left" Margin="37,33,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="pointIdText" HorizontalAlignment="Left" Height="23" Margin="126,33,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
        <Label Content="項目ID" HorizontalAlignment="Left" Margin="37,64,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.923,-0.009"/>
        <TextBox  x:Name="idText" HorizontalAlignment="Left" Height="23" Margin="126,64,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
        <Label Content="項目名" HorizontalAlignment="Left" Margin="37,95,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="itemNameText" HorizontalAlignment="Left" Height="23" Margin="126,95,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
        <Label Content="ソート順" HorizontalAlignment="Left" Margin="37,126,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.203,0.698"/>
        <TextBox x:Name="sortNumText" HorizontalAlignment="Left" Height="23" Margin="126,126,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
        <Button Content="登録" HorizontalAlignment="Left" Height="25" Margin="84,197,0,0" VerticalAlignment="Top" Width="119" Click="SaveButton_Click"/>
    </Grid>
</Page>
```

```csharp:ItemInput.xaml.cs
using EntranceAndExitRecord.Entity;
using EntranceAndExitRecord.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace EntranceAndExitRecord.Views
{
    /// <summary>
    /// ItemInput.xaml の相互作用ロジック
    /// </summary>
    public partial class ItemInput : Page
    {
        public ItemInput()
        {
            InitializeComponent();
        }

        private void SaveButton_Click(object sender, RoutedEventArgs e)
        {
            // 本当はMVVMにのっとってやるべきだけど、今回は動確ということでサボり
            var item = new Item()
            { Id = int.Parse(this.idText.Text),
                ItemName = this.itemNameText.Text,
                PointNo = int.Parse(this.pointIdText.Text),
                SortNum = int.Parse(this.sortNumText.Text)
            };

            using (var db = new EntranceAndExitRecordModel())
            {
                // Insert
                db.Add<Item>(item);
                
                // コミット
                db.SaveChanges();
            }
        }
    }
}
```
DB Browser for SQLiteでINSERTされていることを確認して、データが入ってれば成功。

# 参考
以下のページを参考にさせていただきました。
https://www.slideshare.net/esmsec/entity-framework-core
https://qiita.com/hahifu/items/58819f6f36433f20884d