.NET Blazor Webアプリケーション構築➁ ~~毎度お馴染みEntityFramework~~

## はじめに
ここでは、まずモデルを作成し、EntityFramework(以降 EF)のMigrationを使用し、SQLServerにDataBaseとTableの作成を行っていきます。
ちなみに、前回の投稿はBlazorのセットアップだけです・・・飛ばしちゃっても・・・

https://qiita.com/sharpman/items/977680a1a73be2b15c7a

### Sharedプロジェクトに商品・商品タイプ・商品バリエーション・カテゴリモデルを作成する
#### 商品モデルの作成
C:\project\BlazorApp\BlazorApp\Shared\Product.cs
``` C#
using System.ComponentModel.DataAnnotations;

namespace BlazorApp.Shared
{
    public class Product
    {
        public int Id { get; set; }
        public string Title { get; set; } = string.Empty;
        public string Description { get; set; } = string.Empty;
        public string ImageUrl { get; set; } = string.Empty;
        public bool Featured { get; set; } = false;
        public List<ProductVariant> Variants { get; set; } = new List<ProductVariant>();
    }
}
```
#### 商品タイプモデルの作成
C:\project\BlazorApp\BlazorApp\Shared\ProductType.cs
``` C#
namespace BlazorApp.Shared
{
    public class ProductType
    {
        public int Id { get; set; }
        public string Name { get; set; } = String.Empty;
    }
}
```
#### 商品バリエーションモデルの作成
C:\project\BlazorApp\BlazorApp\Shared\ProductVariant.cs
``` C#
namespace BlazorApp.Shared
{
    public class ProductVariant
    {
        public Product? Product { get; set; }
        public int ProductId { get; set; }
        public ProductType? ProductType { get; set; }
        public int ProductTypeId { get; set; }
        public int Price { get; set; }
        public int OriginalPrice { get; set; }
    }
}
```
### ServerプロジェクトにDBContextクラスを実装する
Entity Frameworkの概念モデルを使用して、データベースへの検索、更新、登録、削除といった基本的な操作は、DbContextクラスを使用していきます。またDBにはSQLServerを使用するため、[SQLServerのインストール](https://www.microsoft.com/ja-jp/sql-server/sql-server-downloads)が必要です。
#### まずは.NET EFがインストールされているか確認しましょ
パッケージマネージャーコンソールを開きコマンドを実行します。
私の場合はすでに6.0.5バージョンがインストールされていました。
``` bash
PM> dotnet ef
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738280/b841c23d-2fa1-a051-2777-c3cc1b7d70a5.png)
最新の状態にしたいのでuninstallしてから再度installします。※すでにインストールされている方は飛ばしてください。最新バージョン**6.0.7** がインストールされました。
``` bash
PM> dotnet tool uninstall --global dotnet-ef
ツール 'dotnet-ef' (バージョン '6.0.5') は正常にアンインストールされました。
PM> dotnet tool install --global dotnet-ef
次のコマンドを使用してツールを呼び出せます。dotnet-ef
ツール 'dotnet-ef' (バージョン '6.0.7') が正常にインストールされました。 
```
### NuGetパッケージ管理を開き以下パッケージをServerプロジェクトにインストールする
- Microsoft.EntityFrameworkCore
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738280/11448521-7650-f755-991b-42ae2b063706.png)

- Microsoft.EntityFrameworkCore.Design
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738280/5af3fe74-01e1-649d-d4c3-89e084097da2.png)

- Microsoft.EntityFrameworkCore.SqlServer
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738280/26f311bc-7cf9-75f5-f103-f6d8b82d65b4.png)

#### DBContextクラスの実装
ServerプロジェクトにDataフォルダを追加します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738280/b664626a-fb26-a923-5d6f-e424f9e32a3a.png)
Dataフォルダ配下にDataContextクラスを実装します。
C:\project\BlazorApp\BlazorApp\Server\Data\DataContext.cs
``` C#
using Microsoft.EntityFrameworkCore;

namespace BlazorApp.Server.Data
{
    public class DataContext : DbContext
    {
        public DataContext(DbContextOptions<DataContext> options) : base(options)
        {

        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<ProductVariant>()
                .HasKey(p => new { p.ProductId, p.ProductTypeId });

            modelBuilder.Entity<ProductType>().HasData(
                    new ProductType { Id = 1, Name = "デジタル" },
                    new ProductType { Id = 2, Name = "絵" }
            );

            modelBuilder.Entity<Product>().HasData(
                    new Product
                    {
                        Id = 1,
                        Title = "おじさんのイラスト",
                        Description = "wikiにあったおじさんのイラストです",
                        ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/0/03/491_BC_-_1902_AD_-_A_Long_Time_Between_Drinks.jpg/1024px-491_BC_-_1902_AD_-_A_Long_Time_Between_Drinks.jpg",
                        Featured = true
                    },
                    new Product
                    {
                        Id = 2,
                        Title = "リアルなアリエルのイラスト",
                        Description = "wikiにあったリアルなアリエルのイラストです",
                        ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7d/Mural_painting_-_Rua_de_Santa_Maria_-_Funchal_02.jpg/1024px-Mural_painting_-_Rua_de_Santa_Maria_-_Funchal_02.jpg"
                    }
                );

            modelBuilder.Entity<ProductVariant>().HasData(
                new ProductVariant
                {
                    ProductId = 1,
                    ProductTypeId = 1,
                    Price = 1368,
                    OriginalPrice = 1500
                },
                new ProductVariant
                {
                    ProductId = 1,
                    ProductTypeId = 2,
                    Price = 1900
                },
                new ProductVariant
                {
                    ProductId = 2,
                    ProductTypeId = 1,
                    Price = 1368,
                    OriginalPrice = 1500
                },
                new ProductVariant
                {
                    ProductId = 2,
                    ProductTypeId = 2,
                    Price = 999,
                    OriginalPrice = 1200
                }
            );
        }

        public DbSet<Product> Products { get; set; }
        public DbSet<ProductType> ProductTypes { get; set; }
        public DbSet<ProductVariant> ProductVariants { get; set; }
    }
}

```
Sharedプロジェクトのモデルは頻繁に利用するので、Program.csの１行目にGlobal Usingを定義しておきましょ。これで、DataContextクラスの参照エラーは直ったはずです。
C:\project\BlazorApp\BlazorApp\Server\Program.cs
``` C#
global using BlazorApp.Shared;
```
#### 接続情報の定義
appsettingsにDefaultConnectionを追加します。
C:\project\BlazorApp\BlazorApp\Server\appsettings.json
``` json
{
  "ConnectionStrings": {
    "DefaultConnection": "Server=localhost\\SQLEXPRESS;Database=blazoreapp;Trusted_Connection=True;"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}
```
また、DataContextに接続情報を設定します。
C:\project\BlazorApp\BlazorApp\Server\Program.cs　10行目あたりに追加してください。
``` C#
// Add services to the container.
builder.Services.AddDbContext<DataContext>(options =>
{
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
});
```
#### Mirationの実行
``` bash
PM> cd .\BlazorApp\Server
dotnet ef migrations add Product
```
Migrationが成功すると,Migrationsフォルダが作成され、Migrationsファイルが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738280/093d273f-c3dd-93ea-5919-70d7adc4e7e7.png)

#### DatabaseのUpdate
``` bash
PM> dotnet ef database update
Build started...
Build succeeded.
```
updateが成功するとDBとテーブルが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738280/79941465-411f-040e-b644-1096688b6618.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738280/7a6b4e4a-e324-1871-03f5-6f09a7cf0a47.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738280/6593ca78-f476-2265-f0e6-4c18980b9b2d.png)

次回はServiceクラスを実装していきます。