Blazor ServerでPostgreSQLをEFCoreで操作する方法

#概要
BlazorServerでPostgreSQLを使用する方法をメモがてら記載します。

#この記事のターゲット
既存のデータベースを使うよ！な方(DBファースト)
データベースがPostgreSQLだよ！な方
EntityFlameWork Coreで操作するよ！な方
#環境
・Visual Studio 2022
・Blazor Server
・.Net6
#プロジェクトを作成する！
Visual Studio 2022を立ち上げて`新しいプロジェクトの作成(N)`を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/6e29a797-5e77-bb4b-4966-ac28a8d8238d.png)
`Blazor Server アプリ`を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/058b9e42-3456-dbe8-1d1a-ef8066df2839.png)
プロジェクト名と保存場所を指定して次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/73bff106-f3be-959d-c043-d08382f7b734.png)
フレームワークと認証の種類を指定して作成
(今回は.Net6.0に認証なし)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/7e298b0f-2f52-fe02-652d-f2c4f93911b1.png)
プロジェクトできた！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/c133e397-a548-e3c8-11c8-811ed32e25f2.png)
#PostgreSQLへの接続設定を追加する
PostgreSQLへの接続文字列を指定します。
ソリューションエクスプローラーの`appsettings.Development.json`を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/cef2975a-576b-5f7e-1333-c14f660d487e.png)


:::note info
便利ポイント
appsettings.jsonに記載した接続文字列はリリース時(発行ビルド)に参照されます。

appsettings.Development.jsonに記載した接続文字列はデバック時に参照されます。

つまり、テスト用のデータベースと本番(運用)用データベースがある場合に接続文字列を書く場所を変えることで勝手に接続するデータベースを変えてくれるってわけだ！いやー便利便利
:::

開いたときの初期データがこれ

```C#:appsettings.Development.json
{
  "DetailedErrors": true,
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  }
}
```

ここにこんな感じで接続文字列を追加する

```C#:appsettings.Development.json
{
  "ConnectionStrings": {
    "db": "Server=192.168.0.999;Port=5432;Database=dbname;User Id=user;Password=user;Pooling=true;"
  },
  "DetailedErrors": true,
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  }
}
```

:::note info
スキーマを指定する方法
スキーマを指定するには接続文字列に"SearchPath=スキーマ名;"を追加します。
:::

つまりスキーマを指定する場合はこんな感じの接続文字列にします。

```C#:appsettings.Development.json
{
  "ConnectionStrings": {
    "db": "Server=192.168.0.999;Port=5432;Database=dbname;User Id=user;Password=user;Pooling=true;SearchPath=selectschema;"
  },
  "DetailedErrors": true,
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  }
}
```

これでデータベースへの接続設定は完了!

#サービスを追加する
さて、こっからが一番ややこしいです。
まず、Program.csを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/90b24272-66cb-8854-0025-f3e94deebe1f.png)
そしたらサービスにDBFactoryを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/422a0056-d310-5a76-59db-58c6d5d63f2d.png)

```C#:DBFactoryサービスを追加
builder.Services.AddDbContextFactory<ApplicationDbContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("db")));
```

コンパイルエラーがでちゃうのでNuGet(ニューゲットって読むらしい)から必要なライブラリを追加します。
まず、ツールバー→プロジェクト→NuGetパッケージの管理を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/359c1e18-089b-3e00-7057-d80bc5dcdd78.png)
参照→EFCoreで検索→Microsoft.EntityFrameWorkCoreを選択→インストールを押下する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/db10967b-90bf-9b1b-80b0-373aa9ed0899.png)

次に、参照→NPGSQLで検索→Npgsql.EntityFrameworkCore.PostgreSQLを選択→インストールを押下する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/aa6c0b54-a96d-6cd2-e19d-39e0fa04a8de.png)


:::note info
バージョンについて
多分ですがバージョンの6.01の6は.Net6の6を指しています。.Net5を使っている人は6.xxのバージョンをインストールしようとするとエラーがでるんじゃないでしょうか？.Net5の人は5.xxのバージョンをインストールするといいかも。
:::

Program.csのUsingステートメントにMicrosoft.EntityFrameworkCoreを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/c990ad77-dba8-b073-b8eb-a794fc8c470c.png)

```C#:参照を追加
using Microsoft.EntityFrameworkCore;
```

これでサービスの追加はOK!!

#DBテーブルの実態クラスを作る

DBテーブルの実態クラスを作っていきます。
まず、クラスを追加します。
今回はDataフォルダに追加します。
Dataフォルダを右クリック→追加→クラス...を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/f4c37528-f43a-f8d1-b4c9-62d8cec1834f.png)
クラスに名前をつけて追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/b7b9ff4f-49ea-44a3-c467-d48ba1266afe.png)
追加した瞬間のソースはこんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/075badcb-6553-9375-8e0a-c48d85e329c2.png)
はじめから出来てるクラスはいらないので消しちゃいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/323b25d5-8568-511d-2564-8487b04c3b1f.png)
そしたらそこにDBのテーブル定義クラスを作成します。
下記の画像でいうと列Idと列Userを持つt_userテーブルです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/4f975082-be39-861f-f1fe-ffa7a054a131.png)
Id列が主キーだとするとこんな感じで主キー設定ができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/2a3a00e8-3d13-508e-04be-a283b9fc5043.png)

```C#:主キーに設定
using System.ComponentModel.DataAnnotations;

namespace PostgreSQLを使いたいなー.Data
{
    public class t_user
    {
        [Key]
        public int Id { get; set; }

        public string User { get; set; } = "";
    }
}
```

これでDBテーブルの実態作成完了！！
#Contextクラスを作成する
感覚としてはスキーマの実態だと思います。違ったらスマソ。
まず、クラスを追加します。
今回はDataフォルダに追加します。
Dataフォルダを右クリック→追加→クラス...を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/3765bc4d-180f-fdf4-4909-038188657c16.png)
クラスに名前をつけて追加します。
クラス名はApplicationDbContextとしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/37748552-a90f-be87-4cd3-ca9a3024e4b8.png)
クラスできた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/e25d25c6-a54f-1783-60e6-7a893aa46f30.png)
DBContextを継承してContextクラスを作成します。
まあ、下のソースをコピペでイケルと思います。(namespaceは要変更)

```C#:DBContextを継承
using Microsoft.EntityFrameworkCore;

namespace PostgreSQLを使いたいなー.Data
{
    public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
             : base(options){ }

    }
}
```

そしたらここにさっき作成したテーブルクラスを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/54d3e178-42d6-4392-db00-0117fc1be91e.png)

```C#:DBSetを追加
public DbSet<t_user> t_user { get; set; }
```

これでContextの作成完了!!

#使い方
使いたいページにDBFactoryをInject(オブジェクトの注入)します。
今回はIndex.razorから使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/5ffbaec7-aed7-5db1-0951-b87b4b51963b.png)

```C#:Index.razor
@page "/"

@using Data
@using Microsoft.EntityFrameworkCore
@inject IDbContextFactory<ApplicationDbContext> DBFactory

<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />

```

こんな感じで使えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/0a09c3dc-56c8-9389-ebfb-92d1cdff4701.png)

```C#:Index.razor
@page "/"

@using Data
@using Microsoft.EntityFrameworkCore
@inject IDbContextFactory<ApplicationDbContext> DBFactory

<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />

@code{
    private void GetUserData()
    {
        using (var dbFactory = DBFactory.CreateDbContext())
        {
            //DBのt_userテーブルのデータをすべて取得する。
            dbFactory.t_user.ToList();
        }
    }
}
```

もし、条件を指定してデータを取得した場合はこんな感じ？

```C#:Index.razor
@page "/"

@using Data
@using Microsoft.EntityFrameworkCore
@inject IDbContextFactory<ApplicationDbContext> DBFactory

<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />

@code{
    private void GetUserData()
    {
        using (var dbFactory = DBFactory.CreateDbContext())
        {
            //DBのt_userテーブルのデータからIdが10以下のものをすべて取得する。
            dbFactory.t_user.Where(x => x.Id <= 10).ToList();
        }
    }
}
```

条件とかテーブルの結合とかはEFCoreの使い方の話になってくるので今回はここまでです。

お疲れさまでした！！