Esercizio: Aggiungere EF Core all'API minima

Completato

Si è uno sviluppatore per un'azienda e l'utente e l'azienda hanno sentito parlare della nuova API minima. Il responsabile ha chiesto di creare un progetto per tale progetto in modo da poter discutere se usarlo nel progetto successivo.

Annotazioni

In questo modulo vengono usati l'interfaccia della riga di comando di.NET e Visual Studio Code per lo sviluppo locale. Una volta completato questo modulo, è possibile applicare i concetti usando Visual Studio (Windows), Visual Studio per Mac (macOS) o lo sviluppo continuo tramite Visual Studio Code (Windows, Linux e macOS).

Questo modulo usa .NET 8.0 SDK. Assicurarsi di avere installato .NET 8.0 eseguendo il comando seguente nel terminale dei comandi preferito:

dotnet --list-sdks

Verrà visualizzato un output simile all'esempio seguente:

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

Assicurarsi che sia elencata una versione che inizia con 8. Se il comando non è presente nell'elenco o non viene trovato, installare la versione più recente di .NET 8.0 SDK.

Configurare il progetto

Prima di tutto, è necessario creare un progetto. È stato installato .NET 6 ed è possibile procedere. In questa unità si aggiungerà la persistenza dei dati a un'API di gestione della pizza.

  1. In un terminale creare un'API Web eseguendo dotnet new:

    dotnet new web -o PizzaStore -f net8.0
    

    Verrà visualizzata la directory PizzaStore .

  2. Passare alla directory PizzaStore immettendo il comando seguente:

    cd PizzaStore
    
  3. Installare il pacchetto Swashbuckle:

    dotnet add package Swashbuckle.AspNetCore --version 6.5.0
    
  4. Aprire il progetto in Visual Studio Code.

  5. Usando Visual Studio Code, creare un file Pizza.cs nella radice del progetto e assegnargli il contenuto seguente:

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

    La classe precedente Pizza è un oggetto semplice che rappresenta una pizza. Questo codice è il modello di dati. In seguito si userà Entity Framework (EF) Core per eseguire il mapping di questo modello di dati a una tabella di database.

  6. Aprire Program.cs e aggiungere il codice evidenziato:

    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();
    

    È possibile che in Visual Studio Code venga richiesto di aggiungere asset per eseguire il debug del progetto. Selezionare Yes nella finestra di dialogo.

Aggiungere EF Core al progetto

Per archiviare gli elementi nell'elenco to-do, installare il EntityFrameworkCore.InMemory pacchetto.

  1. Premere CTRL+' per aprire un terminale in Visual Studio Code. Nel nuovo terminale immettere il codice seguente per aggiungere il pacchetto EF Core InMemory:

    dotnet add package Microsoft.EntityFrameworkCore.InMemory --version 8.0
    
  2. Aggiungere using Microsoft.EntityFrameworkCore; all'inizio dei file Program.cs e Pizza.cs .

    Dopo aver aggiunto EF Core al progetto, è possibile collegare il codice ai dati da salvare ed eseguire query. A tale scopo, creare una PizzaDb classe. La PizzaDb classe eseguirà le attività seguenti:

    • Esporre la Pizzas proprietà dall'elenco di Pizza nel database.
    • Usare UseInMemoryDatabase per collegare l'archiviazione del database in memoria. I dati vengono archiviati qui finché l'app è in esecuzione.
  3. Per configurare il database in memoria, aggiungere il codice seguente alla fine del file Pizza.cs (sopra l'ultimo }). Saranno disponibili due definizioni di classe all'interno dello spazio dei PizzaStore.Models nomi .

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

    DbContext rappresenta una connessione o una sessione utilizzata per eseguire query e salvare istanze di entità in un database.

  4. Aggiungere using PizzaStore.Models; all'inizio del file Program.cs .

  5. In Program.cs, prima della chiamata a AddSwaggerGen, aggiungere il codice seguente:

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

Restituisce un elenco di elementi

  • Per leggere da un elenco di elementi nell'elenco delle pizze, aggiungere il codice seguente sopra la chiamata a per app.Run(); aggiungere una route "/pizzas":

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

Eseguire l'applicazione

  1. Assicurarsi di avere salvato tutte le modifiche. Eseguire l'app chiamando dotnet run nel terminale. Questa azione creerà l'app e la ospiterà su una porta da 5000 a 5300. HTTPS avrà una porta selezionata nell'intervallo 7000-7300.

    Annotazioni

    Se si vuole eseguire l'override del comportamento di selezione delle porte casuali, è possibile impostare le porte da usare in launchSettings.json.

    dotnet run
    

    Di seguito è riportato l'aspetto dell'output nel terminale:

    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. Nel browser, accedere a https://localhost:{PORT}/swagger. Selezionare il GET /pizzas pulsante, seguito da Prova e esegui. Si noterà che l'elenco è vuoto in Response body.

  3. Nel terminale premere CTRL+C per interrompere l'esecuzione del programma.

Creare nuovi elementi

Aggiungere il codice ai POST nuovi elementi all'elenco delle pizze. In Program.cs aggiungere il codice seguente sotto l'oggetto app.MapGet creato in precedenza.

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

Testare l'API

Assicurarsi di aver salvato tutte le modifiche ed eseguire di nuovo l'app. Tornare all'interfaccia utente di Swagger e ora dovrebbe essere visualizzato POST/pizza. Per aggiungere nuovi elementi all'elenco delle pizze:

  1. Selezionare POST /pizza.

  2. Selezionare Prova.

  3. Sostituire il corpo della richiesta con il codice JSON seguente:

    {
        "name": "Pepperoni",
        "description": "A classic pepperoni pizza"
    }
    
  4. Seleziona Execute.

Per leggere gli elementi nell'elenco:

  1. Selezionare GET /pizzas.

  2. Selezionare Prova.

  3. Seleziona Execute.

    Includerà Response body gli elementi appena aggiunti.

    [
      {
        "id": 1,
        "name": "Pepperoni",
        "description": "A classic pepperoni pizza"
      }
    ]
    
  4. Premere CTRL+C nel terminale per interrompere l'esecuzione dell'app. Per il resto di questo esercizio, arrestare e riavviare l'app in base alle esigenze per testare le modifiche. Assicurarsi di salvare tutte le modifiche prima di !dotnet run

Ottenere un singolo elemento

Per OTTENERE un elemento in idbase a , aggiungere il codice nella app.MapPost route creata in precedenza.

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

Testare GET per ID

Per testare questa operazione, è possibile passare a https://localhost:{PORT}/pizza/1 o usare l'interfaccia utente di Swagger. Poiché si usa un database in memoria, la pizza creata in precedenza non verrà elencata se l'applicazione è stata riavviata. Sarà quindi necessario usare l'operazione POST per aggiungerla di nuovo.

Aggiornare un elemento

Per aggiornare un elemento esistente, aggiungere il codice nella GET /pizza/{id} route creata:

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();
});

Test PUT

  1. Selezionare PUT /pizza/{id} nell'interfaccia utente di Swagger.

  2. Selezionare Prova.

  3. Nella casella di testo ID immettere 1.

  4. Infine, aggiornare Request body. Incollare il codice JSON seguente e passare name a Pineapple.

    {
       "id": 1,
       "name": "Pineapple"
    }
    
  5. Seleziona Execute.

Per testare il codice, scorrere verso GET /pizza/{id}. La pizza ha ora il nome Pineapple.

Eliminare un elemento

Per eliminare un elemento esistente, aggiungere il codice in PUT /pizza/{id} cui è stato creato in precedenza:

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();
});

Test DELETE

Provare ora a eliminare un elemento usando l'interfaccia Swagger.

In questa unità EF Core è stato aggiunto a un'applicazione API minima esistente e è stato usato un database in memoria per archiviare i dati. Si apprenderà quindi come usare un database reale per archiviare i dati in modo che venga mantenuto tra gli arresti dell'applicazione.