演習 - 最小 API に EF Core を追加する

完了

あなたは会社の開発者です。会社に、新しい最小 API についての話が伝わってきました。 次のプロジェクトで使用するかどうかを検討できるように、マネージャーからそれに対するプロジェクトの作成を求められています。

Note

このモジュールでは、ローカル開発に .NET CLI (コマンド ライン インターフェイス) と Visual Studio Code を使用します。 このモジュールを終了すると、Visual Studio (Windows)、Visual Studio for Mac (macOS)、または Visual Studio Code (Windows、Linux、macOS) を使った継続的開発を使用して、その概念を適用できます。

このモジュールでは、.NET 8.0 SDK を使います。 適切なコマンド ターミナルで次のコマンドを実行して、.NET 8.0 がインストールされていることを確認します。

dotnet --list-sdks

次の例のような出力が表示されます。

6.0.317 [C:\Program Files\dotnet\sdk]
7.0.401 [C:\Program Files\dotnet\sdk]
8.0.100 [C:\Program Files\dotnet\sdk]

8 で始まるバージョンが一覧に表示されていることを確実にします。 何も表示されない場合、またはコマンドが見つからない場合は、最新の .NET 8.0 SDK をインストールしてください。

プロジェクトのセットアップ

まず、プロジェクトを作成する必要があります。 .NET 6 をインストールしてあり、準備はできています。 このユニットでは、ピザ管理 API にデータ永続化を追加します。

  1. ターミナルで、dotnet new を実行して Web API を作成します。

    dotnet new web -o PizzaStore -f net8.0
    

    PizzaStore のディレクトリが表示されます。

  2. 次のコマンドを入力して、PizzaStore ディレクトリを開きます。

    cd PizzaStore
    
  3. Swashbuckle パッケージをインストールします。

    dotnet add package Swashbuckle.AspNetCore --version 6.5.0
    
  4. Visual Studio Code でプロジェクトを開きます。

  5. Visual Studio Code を使用して、プロジェクト ルートに Pizza.cs ファイルを作成し、次の内容を指定します。

    namespace PizzaStore.Models 
    {
        public class Pizza
        {
              public int Id { get; set; }
              public string? Name { get; set; }
              public string? Description { get; set; }
        }
    }
    

    上の Pizza クラスは、ピザを表す単純なオブジェクトです。 このコードはデータ モデルです。 後で、Entity Framework (EF) Core を使用して、このデータ モデルをデータベース テーブルにマップします。

  6. Program.cs を開き、強調表示されているコードを追加します。

    using Microsoft.OpenApi.Models;
    
    var builder = WebApplication.CreateBuilder(args);
    
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen(c =>
    {
         c.SwaggerDoc("v1", new OpenApiInfo {
             Title = "PizzaStore API",
             Description = "Making the Pizzas you love",
             Version = "v1" });
    });
    
    var app = builder.Build();
    if (app.Environment.IsDevelopment())
    {
       app.UseSwagger();
       app.UseSwaggerUI(c =>
       {
          c.SwaggerEndpoint("/swagger/v1/swagger.json", "PizzaStore API V1");
       });
    }
    
    app.MapGet("/", () => "Hello World!");
    
    app.Run();
    

    Visual Studio Code で、プロジェクトをデバッグするためのアセットを追加するように求めるプロンプトが表示される場合があります。 ダイアログで Yes を選択します。

EF Core をプロジェクトに追加する

項目を To Do リストに格納するには、EntityFrameworkCore.InMemory パッケージをインストールします。

  1. Ctrl+` を押して Visual Studio Code でターミナルを開きます。 新しいターミナルで次のコードを入力して、EF Core InMemory パッケージを追加します。

    dotnet add package Microsoft.EntityFrameworkCore.InMemory --version 8.0
    
  2. using Microsoft.EntityFrameworkCore;Program.csPizza.cs のファイルの一番上に追加します。

    これで、プロジェクトに EF Core が追加され、保存するデータにコードを接続し、クエリを実行することができます。 このステップを実行するには、PizzaDb クラスを作成します。 PizzaDb クラスは、次のタスクを実行します。

    • データベースの Pizza のリストから Pizzas プロパティを公開します。
    • UseInMemoryDatabase を使用してメモリ内データベース ストレージを接続します。 データは、アプリが実行されている間はここに保存されます。
  3. メモリ内データベースを設定するには、Pizza.cs ファイル (最後の } の上) の下部に次のコードを追加します。 PizzaStore.Models 名前空間内に 2 つのクラス定義が指定されます。

    class PizzaDb : DbContext
    {
        public PizzaDb(DbContextOptions options) : base(options) { }
        public DbSet<Pizza> Pizzas { get; set; } = null!;
    }
    

    DbContext は、データベース内のエンティティのインスタンスのクエリおよび保存に使用される接続またはセッションを表します。

  4. using PizzaStore.Models;Program.cs ファイルの先頭に追加します。

  5. Program.cs で、AddSwaggerGen を呼び出す前に次のコードを追加します。

    builder.Services.AddDbContext<PizzaDb>(options => options.UseInMemoryDatabase("items"));
    

項目のリストを返す

  • ピザの一覧の項目の一覧から読み取る場合は、app.Run(); の呼び出しの上に次のコードを追加して、"/pizzas" ルートを追加します。

    app.MapGet("/pizzas", async (PizzaDb db) => await db.Pizzas.ToListAsync());
    

アプリケーションの実行

  1. すべての変更を保存したことを確認します。 ターミナルで dotnet run を呼び出してアプリを実行します。 このアクションにより、アプリがビルドされ、5000 から 5300 のポートでホストされます。 HTTPS では、ポートが 7000 から 7300 の範囲で選択されます。

    Note

    ランダム ポートの選択動作をオーバーライドする場合は、launchSettings.json で使用するポートを設定できます。

    dotnet run
    

    ターミナルでは、出力は次のようになります。

    Building...
     info: Microsoft.Hosting.Lifetime[14]
           Now listening on: https://localhost:7200
     info: Microsoft.Hosting.Lifetime[14]
           Now listening on: http://localhost:5100
     info: Microsoft.Hosting.Lifetime[0]
           Application started. Press Ctrl+C to shut down.
     info: Microsoft.Hosting.Lifetime[0]
           Hosting environment: Development
     info: Microsoft.Hosting.Lifetime[0]
           Content root path: /<path>/PizzaStore
    
  2. ブラウザーで https://localhost:{PORT}/swagger に移動します。 GET /pizzas ボタンを選択し、次に [Try it out](試してみる)[Execute](実行) を選択します。 Response body の下のリストが空であることを確認できます。

  3. ターミナルで Ctrl+C を押して、プログラムの実行を停止します。

新しい項目の作成

ピザのリストに新しい項目を POST するコードを追加しましょう。 Program.cs で、前に作成した app.MapGet の下に次のコードを追加します。

app.MapPost("/pizza", async (PizzaDb db, Pizza pizza) =>
{
    await db.Pizzas.AddAsync(pizza);
    await db.SaveChangesAsync();
    return Results.Created($"/pizza/{pizza.Id}", pizza);
});

API のテスト

すべての変更が保存されていることを確認し、アプリをもう一度実行します。 Swagger UI に戻ると、POST/pizza が表示されます。 ピザ リストに新しい項目を追加するには、次のようにします。

  1. [POST /pizza] を選択します。

  2. [試してみる] を選択します。

  3. 要求本文を次の JSON に置き換えます。

    {
        "name": "Pepperoni",
        "description": "A classic pepperoni pizza"
    }
    
  4. [実行] を選択します。

リストの項目を読み取るには、次のようにします。

  1. [GET /pizzas] を選択します。

  2. [試してみる] を選択します。

  3. [実行] を選択します。

    Response body には、追加したばかりの項目が含まれます。

    [
      {
        "id": 1,
        "name": "Pepperoni",
        "description": "A classic pepperoni pizza"
      }
    ]
    
  4. ターミナルで Ctrl + C キーを押して、アプリの実行を停止します。 この演習の残りの部分では、変更をテストするために、必要に応じてアプリを停止して再起動します。 dotnet run を実行する前に、必ずすべての変更を保存してください。

1 つの項目を取得する

id で項目を GET するには、先ほど作成した app.MapPost ルートの下にコードを追加します。

app.MapGet("/pizza/{id}", async (PizzaDb db, int id) => await db.Pizzas.FindAsync(id));

ID で GET をテストする

この操作を確認するには、https://localhost:{PORT}/pizza/1 にアクセスするか、Swagger UI を使用します。 メモリ内データベースを使用しているため、以前に作成したピザは、アプリケーションを再起動した場合は表示されません。 そのため、POST 操作を使用してもう一度追加する必要があります。

項目を更新する

既存の項目を更新するには、作成した GET /pizza/{id} ルートの下にコードを追加します。

app.MapPut("/pizza/{id}", async (PizzaDb db, Pizza updatepizza, int id) =>
{
      var pizza = await db.Pizzas.FindAsync(id);
      if (pizza is null) return Results.NotFound();
      pizza.Name = updatepizza.Name;
      pizza.Description = updatepizza.Description;
      await db.SaveChangesAsync();
      return Results.NoContent();
});

PUT をテストする

  1. Swagger UI で [PUT /pizza/{id}] を選択します。

  2. [試してみる] を選択します。

  3. [id] テキスト ボックスに「1」と入力します。

  4. 最後に、Request body を更新します。 次の JSON を貼り付け、namePineapple に変更します。

    {
       "id": 1,
       "name": "Pineapple"
    }
    
  5. [実行] を選択します。

コードをテストするには、スクロールして GET /pizza/{id} に戻ります。 ピザに Pineapple という名前が付けられました。

項目を削除する

既存の項目を削除するには、先ほど作成した PUT /pizza/{id} の下にコードを追加します。

app.MapDelete("/pizza/{id}", async (PizzaDb db, int id) =>
{
   var pizza = await db.Pizzas.FindAsync(id);
   if (pizza is null)
   {
      return Results.NotFound();
   }
   db.Pizzas.Remove(pizza);
   await db.SaveChangesAsync();
   return Results.Ok();
});

DELETE のテスト

次に、Swagger インターフェイスを使用して項目を削除してみてください。

このユニットでは、EF Core を既存の最小 API アプリケーションに追加し、メモリ内データベースを使用してデータを格納しました。 次は、実際のデータベースを使用してデータを格納し、アプリケーションがシャットダウンしてもデータが永続化されるようにする方法について説明します。