Упражнение. Использование служб баз данных для сохранения данных из проекта .NET Aspire
В этом упражнении вы замените текущие хранилища данных для находящегося в разработке облачно-ориентированного приложения вашей компании. На данный момент приложение использует локально хранящуюся базу данных SQLite для данных каталога и кэш Redis в памяти для корзин покупок клиента. Существующие хранилища данных заменяются PostgreSQL и MongoDB.
Установка необходимых компонентов
Предварительные требования для .NET Aspire:
- .NET 8
- Предварительная версия Visual Studio 2022
- Docker Desktop или Podman
- Рабочая нагрузка .NET Aspire в Visual Studio
Если у вас уже установлены предварительные требования, можно пропустить клонирование существующего приложения.
Установка .NET 8
Следуйте этой ссылке .NET 8 и выберите правильный установщик операционной системы. Например, если вы используете Windows 11 и современный процессор, выберите пакет SDK x64 .NET 8 для Windows.
После завершения скачивания запустите установщик и следуйте инструкциям. В окне терминала выполните следующую команду, чтобы убедиться, что установка выполнена успешно:
dotnet --version
Вы увидите номер версии установленного пакета SDK для .NET. Например:
8.0.300-preview.24203.14
Установка Предварительной версии Visual Studio 2022
Следуйте этой ссылке на предварительную версию Visual Studio 2022 и выберите Загрузить предварительную версию. После завершения скачивания запустите установщик и следуйте инструкциям.
Установка Docker Desktop
Следуйте этой ссылке Docker Desktop и выберите правильный установщик для вашей операционной системы. После завершения скачивания запустите установщик и следуйте инструкциям.
Откройте приложение Docker Desktop и примите пользовательское соглашение.
Установка рабочей нагрузки .NET Aspire в Visual Studio
Установите рабочую нагрузку .NET Aspire с помощью .NET CLI:
Откройте терминал.
Установите рабочие нагрузки .NET Aspire с помощью следующих команд:
dotnet workload update dotnet workload install aspire dotnet workload list
Вы увидите сведения о рабочей нагрузке .NET Aspire.
Installed Workload Id Manifest Version Installation Source --------------------------------------------------------------------------------------------- aspire 8.0.0/8.0.100 SDK 8.0.300-preview.24203, VS 17.10.34902.84 Use `dotnet workload search` to find additional workloads to install.
Клонирование и изменение приложения "Северные горы"
Используем git
для получения текущего приложения 'Northern Mountains':
В командной строке перейдите в папку, в которой можно работать с кодом.
Выполните следующую команду, чтобы клонировать пример приложения Северные горы e Shop:
git clone -b aspire-databases https://github.com/MicrosoftDocs/mslearn-aspire-starter
Запустите Visual Studio и выберите Открыть проект или решение.
Перейдите в папку, в которой вы клонировали eShop, откройте папку start и выберите файл eShop.databases.sln, а затем выберите Открыть.
В обозревателе решенийразверните eShop.AppHost проект, а затем откройте Program.cs.
// Databases var basketStore = builder.AddRedis("BasketStore").WithRedisCommander(); // Identity Providers var idp = builder.AddKeycloakContainer("idp", tag: "23.0") .ImportRealms("../Keycloak/data/import"); // DB Manager Apps builder.AddProject<Projects.Catalog_Data_Manager>("catalog-db-mgr"); // API Apps var catalogApi = builder.AddProject<Projects.Catalog_API>("catalog-api"); var basketApi = builder.AddProject<Projects.Basket_API>("basket-api") .WithReference(basketStore) .WithReference(idp); // Apps // Force HTTPS profile for web app (required for OIDC operations) var webApp = builder.AddProject<Projects.WebApp>("webapp") .WithReference(catalogApi) .WithReference(basketApi) .WithReference(idp, env: "Identity__ClientSecret");
В предыдущем коде показана текущая конфигурация приложения. Приложение использует кэш Redis для хранилища корзин.
Изучите остальное приложение, сосредоточьтесь на проектах Catalog.Data.Manager и Catalog.API и узнайте, как они используют локальную хранящуюся базу данных SQLite.
Чтобы запустить приложение, нажмите F5 или выберите Отладка > Начать отладку.
Если появится диалоговое окно запуска Docker Desktop, выберите Да.
Когда появится панель мониторинга eShop .NET Aspire, для ресурса веб-приложения выберите безопасную конечную точку:
Приложение открывается в браузере. Вы можете изучить приложение и узнать, как это работает.
Учетные данные тестового пользователя test@example.com и P@$$w0rd1.
Чтобы остановить отладку, нажмите клавиши SHIFT SHIFT+F5или выберите Отладка > остановить отладку.
Добавление компонента .NET Aspire PostgreSQL
Команда, отвечая за микрослужбы каталога, создала приложение для использования локально хранимой базы данных SQLite. Этот подход подходит для разработки, но команда хочет использовать более надежную базу данных для рабочей среды.
Два проекта подключаются к базе данных SQLite: проекты Catalog.Data.Manager и Catalog.API. Диспетчер данных используется только для заполнения базы данных данными, поэтому следует сосредоточиться на проекте Catalog.API.
В обозревателе решенийщелкните правой кнопкой мыши на проекте Catalog.API, выберите Добавить>пакет .NET Aspire.
В поле поиска добавьте Npgsql.EntityFramework в конец и нажмите клавишу ВВОД.
Слева в результатах выберите Aspire.Npgsql.EntityFrameworkCore.PostgreSQL.
Справа выберите раскрывающийся список версий и выберите последнюю версию 8.0.0 выпуска.
Выберите Установить.
Если появится диалоговое окно Предварительный просмотр изменений, выберите Применить.
В диалоговом окне Принятие лицензии выберите Я принимаю.
В Обозревателе решенийвыберите проект Catalog.API, чтобы просмотреть содержимое файла Catalog.API.csproj.
Удалите
PackageReference
для Microsoft.EntityFrameworkCore.Sqlite:<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.3" />
Выполните регистрацию нового DbContext PostgreSQL.
В обозревателе решений разверните проект Catalog.API и откройте файл Program.cs.
Замените SQLite DbContext:
builder.Services.AddDbContext<CatalogDbContext>( options => options.UseSqlite(builder.Configuration.GetConnectionString("sqlconnection") ?? throw new InvalidOperationException( "Connection string 'sqlconnection' not found.")));
С новым DbContext PostgreSQL:
builder.AddNpgsqlDbContext<CatalogDbContext>("CatalogDB");
Приложение больше не должно считывать файл Database.db, поэтому удалите связанные строки в appsettings.json.
В обозревателе решенийв разделе Catalog.APIвыберите appsettings.json.
Удалите записи
ConnectionStrings
, файл теперь выглядит следующим образом:{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "OpenApi": { "Endpoint": { "Name": "Catalog.API v1" }, "Document": { "Description": "The Catalog Microservice HTTP API. This is a Data-Driven/CRUD microservice sample", "Title": "eShop - Catalog HTTP API", "Version": "v1" } }, "CatalogOptions": { "PicBasePathFormat": "items/{0}/pic/" } }
Щелкните право й кнопкой мыши проект каталога.Data.Manager, а затем выберите Удалить.
В диалоговом окне нажмите кнопку ОК.
Команда базы данных создает резервную копию базы данных PostgreSQL для создания и заполнения базы данных каталога. Вы можете просмотреть резервную копию в папке Catalog.API/Seed.
Инициализировать базу данных PostgreSQL с помощью привязанного тома
Проект AppHost может создать контейнер базы данных PostgreSQL, заполнить его данными из привязанного тома, а затем путем внедрения зависимостей передать ссылки на Catalog.API.
В обозревателе решенийщелкните правой кнопкой мыши проект eShop.AppHost, выберите Добавить>пакет .NET Aspire.
В поле поиска добавьте PostgreSQL и нажмите ENTER.
Слева в результатах выберите Aspire.Hosting.PostgreSQL.
Справа выберите раскрывающийся список версий и выберите последнюю версию 8.0.0 выпуска.
Выберите Установить.
Если появится диалоговое окно Предварительный просмотр изменений, выберите Применить.
В диалоговом окне принятия лицензий выберите Я принимаю.
В обозревателе решенийраскройте проект eShop.AppHost, а затем откройте файл Program.cs.
В комментарий
//Databases
добавьте следующий фрагмент кода:// Databases var basketStore = builder.AddRedis("BasketStore").WithRedisCommander(); var postgres = builder.AddPostgres("postgres") .WithEnvironment("POSTGRES_DB", "CatalogDB") .WithBindMount("../Catalog.API/Seed", "/docker-entrypoint-initdb.d").WithPgAdmin(); var catalogDB = postgres.AddDatabase("CatalogDB");
Предыдущий код создает контейнер базы данных PostgreSQL, добавляет базу данных с именем CatalogDBи монтирует каталог /docker-entrypoint-initdb.d к каталогу ../Catalog.API/Seed. Код также создает контейнер для средства pgAdmin, который позволяет управлять базой данных PostgreSQL.
Передайте ссылку
catalogDB
на проект Catalog.API, добавив.WithReference(catalogDB)
, код теперь:// API Apps var catalogApi = builder.AddProject<Projects.Catalog_API>("catalog-api") .WithReference(catalogDB);
Проект catalog.Data.Manager больше не нужен, поэтому удалите проект из AppHost. Удалите этот код:
// DB Manager Apps builder.AddProject<Projects.Catalog_Data_Manager>("catalog-db-mgr");
Тестирование приложения
Использование .NET Aspire позволило команде удалить весь проект. Кроме того, API каталога требует только одной строки кода для добавления контекста базы данных PostgresSQL. Внедрение зависимостей и обнаружение служб из AppHost означает, что для подключения API к новой базе данных не требуется никаких других изменений кода.
Скомпилируйте и запустите приложение, нажмите F5или выберите Отладка > начать отладку.
На панели мониторинга есть два новых контейнера, на которых размещен сервер базы данных PostgreSQL и средство pgAdmin. Существует также ресурс базы данных PostgreSQL, на котором размещена база данных CatalogDB.
Используйте pgAdmin для подключения к базе данных PostgreSQL и изучения данных. Выберите конечную точку postgres pgadmin.
Разверните экземпляры Aspire>postgres>Базы данных>CatalogDB>Схемы>каталог>Таблицы. Затем щелкните правой кнопкой мыши таблицу каталога и выберите Просмотр и изменение данных>первых 100 строк.
Вы можете увидеть данные, загруженные AppHost.
Выберите вкладку панели мониторинга ресурсов eShop в браузере, а затем выберите конечную точку доступа веб-приложения.
Приложение открывается и работает как раньше.
Чтобы остановить отладку, нажмите клавиши SHIFT +F5или выберите Отладка > Остановить отладку.
Добавление компонента .NET Aspire MongoDB в приложение
Текущее приложение использует Redis в качестве хранилища данных в памяти для корзины покупок клиента. Команда хочет использовать более надежное и устойчивое хранилище данных для корзины. Замените кэш Redis базой данных MongoDB.
Измените Basket.API для использования MongoDB
- В обозревателе решенийщелкните правой кнопкой мыши проект Basket.API, выберите Добавить, а затем выберите Добавить>пакет Aspire .NET.
- В поле поиска введите в конце MongoDB и нажмите клавишу ВВОД.
- Выберите Aspire.MongoDB.Driver, а затем выберите последнюю версию 8.0.0.
- Выберите Установить.
- Если появится диалоговое окно Предварительные изменения, выберите Применить.
- В диалоговом окне принятия лицензий выберите Я принимаю. @
Создание хранилища корзины MongoDB
Микрослужба корзины использует HostingExtensions
для управления хранилищем данных Redis. Замените хранилище данных Redis хранилищем данных MongoDB.
В обозревателе решений последовательно разверните проект Basket.API и папку Storage, затем выберите файл RedisBasketStore.cs.
Существует два асинхронных метода,
GetBasketAsync
иUpdateBasketAsync
, которые используют кэш Redis. Давайте создадим версии этих методов для MongoDB.В обозревателе решенийщелкните правой кнопкой мыши папку хранилища, а затем выберите Добавить>Класс.
В диалоговом окне Добавление нового элемента назовите файл MongoBasketStore.cs, а затем выберите Добавить.
Замените код в файле MongoBasketStore.cs следующим кодом:
using eShop.Basket.API.Models; using MongoDB.Driver; using MongoDB.Driver.Linq; namespace eShop.Basket.API.Storage; public class MongoBasketStore { private readonly IMongoCollection<CustomerBasket> _basketCollection; public MongoBasketStore(IMongoClient mongoClient) { // The database name needs to match the created database in the AppHost _basketCollection = mongoClient.GetDatabase("BasketDB").GetCollection<CustomerBasket>("basketitems"); } public async Task<CustomerBasket?> GetBasketAsync(string customerId) { var filter = Builders<CustomerBasket>.Filter.Eq(r => r.BuyerId, customerId); return await _basketCollection.Find(filter).FirstOrDefaultAsync(); } public async Task<CustomerBasket?> UpdateBasketAsync(CustomerBasket basket) { var filter = Builders<CustomerBasket>.Filter.Eq(r => r.BuyerId, basket.BuyerId); var result = await _basketCollection.ReplaceOneAsync(filter, basket, new ReplaceOptions { IsUpsert = true }); return result.IsModifiedCountAvailable ? basket : null; } }
Предыдущий код создает класс
MongoBasketStore
, который работает с модельюCustomerBasket
. Коллекция обрабатывает операции CRUD для корзин покупок клиентов в базе данных MongoDB.В обозревателе решенийразверните Basket.API>расширения и затем выберите файл HostingExtensions.cs.
Замените код Redis:
builder.AddRedis("BasketStore"); builder.Services.AddSingleton<RedisBasketStore>();
С помощью кода MongoDB:
builder.AddMongoDBClient("BasketDB"); builder.Services.AddSingleton<MongoBasketStore>();
В обозревателе решений разверните папку Grpc, а затем откройте файл BasketService.cs.
Измените класс так, чтобы он принимал значение
MongoBasketStore
, и замените:public class BasketService(RedisBasketStore basketStore) : Basket.BasketBase
С:
public class BasketService(MongoBasketStore basketStore) : Basket.BasketBase
Добавление базы данных MongoDB в AppHost
В Обозревателе решенийщелкните правой кнопкой мыши проект eShop.AppHost и выберите Добавить>пакет .NET Aspire.
В поле поиска введите в конце MongoDB и нажмите Enter.
Выберите пакет Aspire.Hosting.MongoDB, а затем выберите последнюю версию 8.0.0.0.
Выберите Установить.
Если появится диалоговое окно предварительных изменений, выберите Применить.
В диалоговом окне принятия лицензий выберите Я принимаю. @
В Обозревателе решенийразверните проект eShop.AppHost , а затем откройте файл Program.cs.
В разделе "Базы данных" добавьте компонент MongoDB:
var mongo = builder.AddMongoDB("mongo") .WithMongoExpress() .AddDatabase("BasketDB");
Предыдущий код создает контейнер базы данных MongoDB, добавляет базу данных с именем BasketDB. Код также создает контейнер для инструмента Mongo Express, который позволяет управлять базой данных MongoDB.
Удалите контейнер Redis:
var basketStore = builder.AddRedis("BasketStore").WithRedisCommander();
Теперь код должен выглядеть следующим образом:
// Databases var postgres = builder.AddPostgres("postgres") .WithEnvironment("POSTGRES_DB", "CatalogDB") .WithBindMount("../Catalog.API/Seed", "/docker-entrypoint-initdb.d") .WithPgAdmin(); var catalogDB = postgres.AddDatabase("CatalogDB"); var mongo = builder.AddMongoDB("mongo") .WithMongoExpress() .AddDatabase("BasketDB");
Для проекта Basket.API требуется ссылка на новую базу данных MongoDB, и необходимо удалить ссылку Redis:
var basketApi = builder.AddProject<Projects.Basket_API>("basket-api") .WithReference(mongo) .WithReference(idp);
Проект Basket.API теперь готов к использованию базы данных MongoDB. Давайте протестируем приложение, чтобы узнать, работает ли оно.
Тестирование приложения
Скомпилируйте и запустите приложение, нажмите F5или выберите Отладка > начать отладку.
На панели мониторинга можно увидеть новые контейнеры MongoDB, один для сервера базы данных, другой для Mongo Express. Существует также новый ресурс MongoDBDatabase, на котором размещена база данных BasketDB .
Выберите конечную точку веб-приложения.
Чтобы войти с помощью учетных данных тестового пользователя, щелкните значок пользователя в правом верхнем углу. Электронная почта test@example.com, а пароль — P@$$w0rd1.
Выберите часы Adventurer GPS на домашней странице.
Выберите Добавить в корзину, и вы увидите исключение:
Отладка приложения
Приложение создает исключение при попытке добавить элемент в корзину покупок. Панель мониторинга можно использовать для отладки проблемы.
Выберите вкладку ресурсов eShop панели мониторинга в браузере.
На панели мониторинга отображаются ошибки в api корзины и веб-приложения. Просмотрите журналы корзины API.
Для ресурса basket-api в столбце Logs выберите Просмотр.
Существует исключение:
System.FormatException: Element '_id' does not match any field or property of class eShop.Basket.API.Models.CustomerBasket.
Выберите пункт меню Ресурсы, а затем выберите конечную точку mongo-mongoexpress.
В разделе баз данных рядом с BasketDBвыберите Вид.
В коллекциирядом с элементами корзинывыберите Просмотр.
Документы, хранящиеся в MongoDB, имеют поле _id. Каждый документ, хранящийся в коллекции MongoDB, должен иметь уникальное поле _id.
Чтобы остановить отладку, нажмите клавиши SHIFT SHIFT+F5или выберите Отладка > остановить отладку.
Просмотрите код и исправьте проблему
Давайте рассмотрим CustomerBasketи посмотрим, можно ли найти проблему.
В обозревателе решенийразверните папку Basket.API>Models, а затем откройте файл CustomerBasket.cs.
public class CustomerBasket { public required string BuyerId { get; set; } public List<BasketItem> Items { get; set; } = []; }
Модель CustomerBasket не имеет поля или свойства, соответствующего полю _id. Платформа сущностей пытается сопоставить поле _id с моделью CustomerBasket, и она не может найти совпадение.
Обновите модель
CustomerBasket
, чтобы включить поле _id:public class CustomerBasket { /// <summary> /// MongoDB document identifier /// </summary> public string _id { get; set; } = ""; public required string BuyerId { get; set; } public List<BasketItem> Items { get; set; } = []; }
Тестирование фиксированного приложения
Чтобы скомпилировать и запустить приложение, нажмите клавишу F5или выберите Отладка > начать отладку.
Для веб-приложенияв столбце конечных точек щелкните URL-адрес правой кнопкой мыши и выберите Открыть ссылку в окне InPrivate.
Использование окна InPrivate гарантирует, что браузер не использует файл cookie предыдущего сеанса для проверки подлинности.
Чтобы войти с помощью учетных данных тестового пользователя, щелкните значок пользователя в правом верхнем углу. Электронная почта — test@example.com, а пароль — P@$$w0rd1.
Выберите Adventurer GPS Watch на домашней странице.
Выберите Добавить в сумку покупок.
Теперь работает корзина приложений "Северные горы".
База данных SQLite успешно заменена базой данных PostgreSQL и кэшом Redis на базу данных MongoDB. Вы использовали .NET Aspire для управления базами данных и изучения данных в них, и вы использовали панель мониторинга для отладки проблемы с приложением.