AccessデータベースでEntityFrameworkを使ったコードファーストなモデル開発

# はじめに
EntityFrameworkはOleDBに非対応で事実上利用不可、
UWPではついにSQLiteにその座を奪われたりと、
もはや過去の遺物みたいな扱いを受けてるAccessですが、
JetEntityFrameworkなるものを見つけたので、試してみます。

## 参考
[Microsoft Access Entity Framework Provider - GitHub](https://github.com/bubibubi/JetEntityFrameworkProvider)

# 作ってみる

## 環境など
- Visual Studio 2015 Update3
- Access 2010（.accdb 2007-2010形式）
- JetEntityFrameworkProvider v1.2.6

## 新規プロジェクトの作成

- Windowsクラシックなアプリ（.Net 4.6.1）を新規作成します。
![VS New Project](https://qiita-image-store.s3.amazonaws.com/0/107323/6953fb9f-5ebc-17a5-8e47-83976865013a.png)
今回はC#＆WPFを選んでいますが、VB＆Windowsフォームでも同じ手順で実装可能です。  

## 新規データベースの作成
- Accessからデータベースファイルを作成します。  
ここでは`C:\Temp\Main.accdb`に置きました。
![Access New Database](https://qiita-image-store.s3.amazonaws.com/0/107323/cda0d36d-f5a2-95f4-30ef-0862780a99cc.png)
この時点ではまだテーブルも何も存在しません。

ちなみにこのJetEntityFrameworkですがaccdbでなくmdbも対応しているそうです。
（OleDbでいけるから当然といえば当然）

VB＆Windowsフォームでmdb…
~~負の遺産~~レガシーな業務アプリを細々と運用する現場には
あながちありがちな組み合わせではないでしょうか。

## ライブラリインストール
NuGetパッケージマネージャを開き、JetEntityFrameworkをインストールします。
（依存関係のEntityFramework6は勝手についてきます。）
![SnapCrab_NoName_2017-3-4_23-10-8_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/107323/3ca82ed5-48bc-4a85-a58c-fa5e6f696f25.png)

## データベースの接続情報
`App.config`に先ほど作成したAccessデータベースのConnectionStringsを追記します。
`MainConnection`の名前で作成しました。

```xml:App.config
  <connectionStrings>
    <add name="MainConnection" connectionString="Provider=Microsoft.Ace.OleDb.12.0;Data Source = C:\Temp\Main.accdb"
         providerName="JetEntityFrameworkProvider"/>
  </connectionStrings>
```

## POCO Entityクラスの作成
コードファーストなので、まずはモデルを表すコードを書きます。
クラス名がテーブル名、プロパティがフィールド名になります。

* 仮に商品マスターを分類管理するようなイメージで作ってみます。

```C#
    class Shohin
    {
        public int Sku { get; set; }
        public string Jan { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
        public virtual List<Bunrui> Bunrui { get; set; }
    }

    class Bunrui
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public virtual List<Shohin> Shohin { get; set; }
    }
```

## Contextクラスの作成
Entityクラスとデータベースの橋渡しとなるのがコンテキストクラスです。
`DbContext`を継承した`Context`クラスを作成します。

- `System.Data.Entity`名前空間のクラスを使っていきます。

```C#
using System.Data.Entity;
```

- 継承元のコンストラクタに先ほど`App.config`で定義した`MainConnection`を引数で渡します。  
これが、この`Context`クラスを使用する際の接続情報になります。
- DbSet<Entity>プロパティを定義して、テーブルとEntityクラスをマッピングします。
- Fluent APIを利用し、`OnModelCreating`メソッド内で`Shohin`クラスの主キーに`Sku`プロパティを指定しています。  
（EFの規約ではプロパティ名が`Id`のものが主キーとされるため、`Id`が無い`Shohin`クラスはこのままでは使えません。）

```C#
    class Context:DbContext
    {
        public Context() : base("MainConnection")
        {
        }

        public DbSet<Shohin> Shohin { get; set; }
        public DbSet<Bunrui> Bunrui { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Shohin>()
                .HasKey( _ => _.Sku);
        }
    }
```

## アプリ起動、テーブル生成

準備は整ったので、実際にテーブルが生成されるところを確認します。

- メインフォームのコンストラクタに先ほどの`Context`クラスを使う処理を追記。  
とりあえず商品マスタの個数を数える感じで。


```C#
        public MainWindow()
        {
            InitializeComponent();

            using (var context = new Context())
            {
                Console.WriteLine(context.Shohin.Count());      
            }
        }
```

- アプリをビルド＆実行します。
ここまでにミスが無ければ、さくっとアプリが立ち上がると思います。

- Accessデータベースを見てみます。
`Shohin`と`Bunrui`に多対多の関係を持たせたので、テーブル`Shohins`、`Bubruis`、
そして中間テーブル`ShohinBunruis`の3テーブルが作成されました。賢いですね！
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/107323/e0917a19-04d9-2c9c-f6f9-04aef24ccdfc.png)
（クラス名/テーブル名に日本語使ってしまったので複数形が残念なテーブル名になってます…）

# おわりに
Fluent APIも使えますし、
通常のEntityFrameworkと同じ形で違和感なくAccessが扱えるようです。

EFv1は2008年リリースです。今更EFなんて～、と思う人も多いと思うんですが、
このJetEntityFrameworkが2015年に登場して、未だそれなりに更新されているあたりに
Accessの根強い人気（？）根深い闇（？）を感じます。