Übung: Hinzufügen eines Datenspeichers

Der Klassentyp Model ist erforderlich, um ein Hundespielzeug im Bestand darzustellen. Die Model-Klasse muss die Eigenschaften eines Produkts enthalten und wird dazu verwendet, Daten an die Web-API zu übergeben. Sie wird ebenfalls zur Beibehaltung von Hundespielzeug in einem Datenspeicher verwendet. Der Datenspeicher, der im Rahmen dieser Lerneinheit erstellt wird, wird als In-Memory Database von EF Core erstellt.

In dieser Lerneinheit wird der Einfachheit halber eine In-Memory Database verwendet. Für Produktionsumgebungen sollten Sie einen anderen Datenspeicher auswählen, z. B. SQL Server oder Azure SQL-Datenbank.

Wichtig

Wenn in der Cloud Shell-Sitzung jemals ein Timeout auftritt oder die Verbindung getrennt wird, stellen Sie nochmals eine Verbindung her, und führen Sie anschließend den folgenden Befehl aus, um das Arbeitsverzeichnis auf ~/aspnet-learn/src/ContosoPets.Api festzulegen und den Editor zu starten:

cd ~/aspnet-learn/src/ContosoPets.Api && code .
  1. Führen Sie den folgenden Befehl aus:

    dotnet add package Microsoft.EntityFrameworkCore.InMemory
    

    Der vorherige Befehl:

    • Fügt dem Projekt den angegebenen NuGet-Paketverweis hinzu.
    • Lädt das angegebene NuGet-Paket und seine Abhängigkeiten herunter.

    Das Microsoft.EntityFrameworkCore.InMemory-Paket ist erforderlich, um EF Core in In-Memory Databases verwenden zu können.

  2. Führen Sie den folgenden Befehl aus:

    mkdir Models && touch $_/Product.cs
    

    Hinweis

    Der Befehl touch ist spezifisch für Linux, das zugrundeliegende Betriebssystem von Cloud Shell.

    Im Projektstamm wird ein Verzeichnis Models mit einer leeren Datei Product.cs erstellt. Der Verzeichnisname Models entspricht einer Konvention. Der Name stammt aus der MVC-Architektur (Model-View-Controller), die von der Web-API verwendet wird.

  3. Aktualisieren Sie den Datei-Explorer, indem Sie auf das Aktualisierungssymbol im Editor klicken.

    Cloud Shell-Aktualisierungssymbol

    Das Verzeichnis Models und die Datei Product.cs wird angezeigt.

  4. Fügen Sie den folgenden Code zu Models/Product.cs hinzu, um ein Produkt zu definieren. Speichern Sie die Änderungen.

    using System.ComponentModel.DataAnnotations;
    
    namespace ContosoPets.Api.Models
    {
        public class Product
        {
            public long Id { get; set; }
    
            [Required]
            public string Name { get; set; }
    
            [Required]
            [Range(minimum: 0.01, maximum: (double) decimal.MaxValue)]
            public decimal Price { get; set; }
        }
    }
    

    Tipp

    Die folgenden Tastenkombinationen sind im Cloud Shell-Editor nützlich.

    Tastenkombinationen Befehl
    STRG+V (Windows)
    ⌘+V (macOS)
    Einfügen
    STRG+S (Windows)
    ⌘+S (macOS)
    Speichern

    Die Eigenschaften Name und Price werden als erforderlich gekennzeichnet, um sicherzustellen, dass Werte bei der Erstellung eines Product-Objekts bereitgestellt werden. Darüber hinaus erzwingt die Price-Eigenschaft Mindest- und Höchstwerte.

  5. Führen Sie den folgenden Befehl aus:

    mkdir Data && touch $_/ContosoPetsContext.cs $_/SeedData.cs
    

    Im Projektstamm wird ein Verzeichnis Data mit den leeren Dateien ContosoPetsContext.cs und SeedData.cs erstellt.

  6. Aktualisieren Sie den Datei-Explorer, und fügen Sie den folgenden Code zu Data/ContosoPetsContext.cs hinzu. Speichern Sie die Änderungen.

    using Microsoft.EntityFrameworkCore;
    using ContosoPets.Api.Models;
    
    namespace ContosoPets.Api.Data
    {
        public class ContosoPetsContext : DbContext
        {
            public ContosoPetsContext(DbContextOptions<ContosoPetsContext> options)
                : base(options)
            {
            }
    
            public DbSet<Product> Products { get; set; }
        }
    }
    

    Mit dem obigen Code wird eine Contoso Pets-spezifische Implementierung eines EF Core-DbContext-Objekts erstellt. Die Klasse ContosoPetsContext ermöglicht den Zugriff auf eine In-Memory Database, die im nächsten Schritt konfiguriert wird.

  7. Fügen Sie den folgenden hervorgehobenen Code der Methode ConfigureServices der Datei Startup.cs hinzu. Speichern Sie die Änderungen.

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ContosoPetsContext>(options =>
            options.UseInMemoryDatabase("ContosoPets"));
        services.AddControllers();
    }
    

    Der obige Code:

    • Registriert die benutzerdefinierte Klasse DbContext namens ContosoPetsContext mithilfe des Dependency Injection-Systems (Abhängigkeitsinjektion) von ASP.NET Core.
    • Definiert eine In-Memory Database namens ContosoPets.
  8. Fügen Sie am Anfang von Startup.cs den folgenden Code hinzu. Speichern Sie die Änderungen.

    using Microsoft.EntityFrameworkCore;
    using ContosoPets.Api.Data;
    

    Der Namespace Microsoft.EntityFrameworkCore löst den Methodenaufruf UseInMemoryDatabase auf, und der Namespace ContosoPets.Api.Data löst den Verweis ContosoPetsContext auf.

  9. Fügen Sie den folgenden Code zu Data/SeedData.cs hinzu. Speichern Sie die Änderungen.

    using System;
    using System.Linq;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.DependencyInjection;
    using ContosoPets.Api.Models;
    
    namespace ContosoPets.Api.Data
    {
        public static class SeedData
        {
            public static void Initialize(ContosoPetsContext context)
            {
                if (!context.Products.Any())
                {
                    context.Products.AddRange(
                        new Product
                        {
                            Name = "Squeaky Bone",
                            Price = 20.99m,
                        },
                        new Product
                        {
                            Name = "Knotted Rope",
                            Price = 12.99m,
                        }
                    );
    
                    context.SaveChanges();
                }
            }
        }
    }
    

    Mit dem obigen Code wird eine statische SeedData-Klasse definiert. Mit der Methode Initialize der Klasse wird das Seeding für die In-Memory Database mit zwei Hundespielzeugen durchgeführt.

  10. Ersetzen Sie den Code in Program.cs durch folgenden Code. Speichern Sie die Änderungen.

    using System;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;
    using ContosoPets.Api.Data;
    
    namespace ContosoPets.Api
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                var host = CreateHostBuilder(args).Build();
                SeedDatabase(host);
                host.Run();
            }
    
            public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        webBuilder.UseStartup<Startup>();
                    });
    
            private static void SeedDatabase(IHost host)
            {
                var scopeFactory = host.Services.GetRequiredService<IServiceScopeFactory>();
                using var scope = scopeFactory.CreateScope();
                var context = scope.ServiceProvider.GetRequiredService<ContosoPetsContext>();
    
                if (context.Database.EnsureCreated())
                {
                    try
                    {
                        SeedData.Initialize(context);
                    }
                    catch (Exception ex)
                    {
                        var logger = scope.ServiceProvider.GetRequiredService<ILogger<Program>>();
                        logger.LogError(ex, "A database seeding error occurred.");
                    }
                }
            }
        }
    }
    

    Die Program.Main-Methode wird bei Start der App als erstes ausgeführt. Mit den oben genannten Änderungen wird das Seeding der In-Memory Database über einen Aufruf von SeedData.Initialize ausgelöst.

    Wichtig

    Von dieser Strategie für das Seeding der Datenbank wird in Produktionsumgebungen abgeraten. Erwägen Sie stattdessen das Seeding während der Bereitstellung der Datenbank.

  11. Führen Sie den folgenden Befehl aus, um die App zu erstellen:

    dotnet build
    

    Der Buildvorgang sollte erfolgreich und ohne Warnungen abgeschlossen werden. Wenn beim Buildvorgang ein Fehler auftritt, suchen Sie in der Ausgabe nach Informationen zur Problembehandlung.

Die Model-Klasse Product und die Klasse ContosoPetsContext werden vom Controller verwendet, der in der nächsten Lerneinheit erstellt wird.