Chapter 3: Using database and storage components
The introduction explains why the e-commerce app needs databases and establishes that Aspire integration libraries support both relational and NoSQL databases.
After this chapter you will be able to
- Aspire database integration range. Explain that Aspire integration libraries can connect applications to SQL-based relational databases and to NoSQL databases, including document stores and key-value stores.
- Existing database connection flow. Explain how to register an existing database connection in Aspire and make it available to services, regardless of database type.
- Service discovery for databases. Explain how Aspire integrations simplify connecting an application to a SQL-based relational database.
- Host and client library roles. Distinguish what the Aspire host library does from what a database client library lets a service do, including the local and production resource options described here.
- Product entity model. Describe how a C# entity model represents database records, using the online shop’s Product model as an example. Explain what its Id, Key, and MaxLength declarations do.
- Product DTO contents. Explain why the API returns a product DTO rather than necessarily sending the database entity to the UI, and identify the product information this DTO carries.
- Database-agnostic UI boundary. Explain how a separate DTO lets the presentation and infrastructure layers exchange data without depending on each other’s implementation details.
- Product display UI changes. Describe the OnlineShop.Web changes that replace the sample weather UI with a product display, including the API client, its DI registration, the home page, and obsolete pages and links.
- SQL Server host setup. Describe how the Aspire host adds a SQL Server container and how its administrator password and port are chosen by default or configured explicitly.
- Database creation and naming. Explain what AddDatabase() does in the Aspire version described here and distinguish the database resource name from the database it can reference.
- Container lifetime and data. Justify making the development SQL Server container's lifetime persistent and distinguish that choice from the recommended production database approach.
- Service database dependency. Describe how the host gives a service its database reference and delays that service until the database is ready.
- SQL Server client registration. Explain how the consuming API registers the ADO.NET SQL Server client and obtains a connection without constructing its own connection string.
- Product database example flow. Trace how the example uses the SQL client to create a Shop database and product table, populate the table if empty, and return queried data from an API endpoint.
- Entity Framework client switch. Explain that using Entity Framework changes the API service’s database client, not the SQL Server instance hosted by Aspire, and identify the NuGet package added to the API project.
- DbContext registration and connection. Describe how ProductsDbContext represents the products database, is registered for dependency injection, and uses the Aspire host’s connection string through the sqldb connection name.
- Azure SQL resource registration. Describe how to register Azure SQL Server in an Aspire host using Aspire.Hosting.Azure.Sql and AddAzureSqlServer(), then register its database with AddDatabase().
- Local and Azure behavior. Explain why the default AddAzureSqlServer() setup is suited to Azure deployment but does not provide a working local Docker database.
- Oracle host registration. Describe how to host an Oracle database in Aspire: install Aspire.Hosting.Oracle in the host project, then create a database server container and database reference.
- Oracle Entity Framework client. Describe the consuming service's Oracle client setup and how application data-access code compares with other database providers.
- PostgreSQL host registration. Describe how Aspire registers a PostgreSQL server and database, and distinguish what AddDatabase() does in the current Aspire version versus version 8.
- PostgreSQL client approaches. Distinguish the raw-SQL and Entity Framework options for consuming PostgreSQL, including what the registered NpgsqlDataSource provides and why Entity Framework uses LINQ.
- Database connection string resolution. Explain how a hosted service obtains its database connection string with an Aspire-specific client package and where to find it when using another library.
- Meaning and diversity of NoSQL. Explain that NoSQL refers to storage outside the traditional relational structure, not necessarily to databases that never use SQL. Describe why the name does not identify one shared database type or standard.
- Four NoSQL storage models. Distinguish document, key-value, graph, and column-family stores by how each organizes data.
- Problem fit by storage model. Explain the section’s examples of when key-value, column-family, graph, and document stores are useful, rather than assuming a relational database suits every problem.
- MongoDB document model. Describe how MongoDB stores data in BSON documents grouped into collections rather than SQL tables and rows, and how a document can hold related data such as a product and its reviews.
- Document store tradeoffs. Explain why MongoDB can suit flexible or rapidly evolving applications while being difficult to use when relationships between separate entities must be tracked.
- MongoDB hosting and service reference. Describe how to host MongoDB in Aspire and connect a service to its database reference.
- MongoDB client registration. Explain how a hosted service registers a MongoDB client and obtains its connection configuration through Aspire.
- Product review data flow. Trace how the example obtains a MongoDB collection, seeds it when empty, and makes its product reviews available through an API endpoint.
- Global distribution and replication. Explain how Cosmos DB’s distribution and replication across Azure regions support availability and low-latency access.
- Data models and API choices. Describe how Cosmos DB supports multiple NoSQL data models and lets developers choose APIs for different uses, giving examples from the section.
- Cosmos DB host configuration. Describe how to enable and register a Cosmos DB component in the Aspire host, and distinguish connecting to Azure from using an emulator for local debugging.
- Service reference to Cosmos DB. Explain how a service that uses the hosted Cosmos DB component is given a reference to it.
- Cosmos DB client registration. Explain how a service hosted by Aspire registers a Cosmos DB client and why the registration name must match the name used in the host app.
- Storage subservice roles. Distinguish Table Storage as flat, unrelated NoSQL tables suited to reference data; Blob Storage as cloud file storage; and Queue Storage as a way for services to exchange messages rather than a database.
- Azure Table Storage hosting. Explain why Aspire uses a common Azure Storage component and describe the stated steps for hosting Table Storage, including the emulator and real-resource options.
- Required table entity columns. Explain the roles of PartitionKey, RowKey, ETag, and Timestamp in a Table Storage entity.
- Table seeding and retrieval. Trace the described flow for seeding Table Storage and making its data available through an API endpoint.
- Blob Storage integration setup. Explain that Blob Storage holds files such as downloadable product specifications, and distinguish the package used to host an emulated instance from the package installed in the service that accesses it.
- Product specifications CSV seeding. Describe how the initial product specifications are stored as a CSV file in the products blob container, including what happens when the container or file already exists.
What it builds on
- How Aspire integration libraries differ from containers (chapter 2) · Introduces Aspire integration libraries.
- Using service discovery (chapter 1) · Assumes familiarity with services using resource names for Aspire service discovery.
- Service discovery in Aspire (chapter 1) · The earlier introduction to Aspire service discovery.
- Introducing service defaults (chapter 1) · The existing OnlineShop.ServiceDefaults project.
- Adding a Keycloak container to an Aspire host (chapter 2) · Hosting a container from an Aspire host.
- Docker containers (chapter 2) · The use of Docker containers for infrastructure components.
- Connecting to an integration from a hosted service (chapter 2) · Connecting a hosted service to an Aspire integration
- Configuring Aspire integrations on the host (chapter 2) · Configuring Aspire integrations on the host.
Section by section
Introduction
The introduction explains why the e-commerce app needs databases and establishes that Aspire integration libraries support both relational and NoSQL databases.
- Aspire database integration range: Explain that Aspire integration libraries can connect applications to SQL-based relational databases and to NoSQL databases, including document stores and key-value stores.
Why it matters: This frames Aspire as useful with more than one kind of database. - E-commerce application data needs: Explain why the e-commerce app needs a database, using its products and customer orders as examples of data to store.
Why it matters: The app’s products and orders give a concrete reason to add data storage.
Key terms: Aspire integration libraries, SQL-based relational database management systems (RDBMSs), NoSQL databases, document stores, key-value stores, e-commerce app, products, orders, databases
3.1 Connecting Aspire to an existing database
This section explains how an Aspire application connects its services to an existing database through an AppHost connection-string resource.
- Existing database connection flow: Explain how to register an existing database connection in Aspire and make it available to services, regardless of database type.
Why it matters: It lets services use an existing database without each service carrying its own copy of the connection string.
Key terms: AppHost.cs, AddConnectionString(), ConnectionStrings, resource name, service discovery
3.2 SQL database components basics
This section explains how Aspire SQL integrations connect applications to relational databases through service discovery, host and client libraries, and a choice of data-access approaches.
- Service discovery for databases: Explain how Aspire integrations simplify connecting an application to a SQL-based relational database.
Why it matters: This is a central reason the section gives for using Aspire integrations with relational databases. - Host and client library roles: Distinguish what the Aspire host library does from what a database client library lets a service do, including the local and production resource options described here.
Why it matters: The distinction separates setting up a database resource from using its data within a service. - Choice of SQL access: Describe the two approaches to working with SQL in C# that Aspire database client libraries can support.
Why it matters: Aspire does not force every service to adopt the same way of accessing SQL data.
Key terms: Aspire integrations, RDBMS, database connection strings, service discovery, host library, consumer library, client libraries, container, persistent managed database instance, object-relational mapper
3.2.1 Working with the SQL data model
This section defines the product database entity and the DTO used to send product information from the API to the UI.
- Product entity model: Describe how a C# entity model represents database records, using the online shop’s Product model as an example. Explain what its Id, Key, and MaxLength declarations do.
Why it matters: The entity model describes the data the API works with in the database. - Product DTO contents: Explain why the API returns a product DTO rather than necessarily sending the database entity to the UI, and identify the product information this DTO carries.
Why it matters: A focused DTO gives the UI the product information it needs without sending irrelevant database fields. - Shared DTO contract: Justify keeping one DTO definition in a library referenced by both the API and frontend, and state where this example places it.
Why it matters: A shared definition helps the API and frontend agree on the data they exchange.
Key terms: entity model, Product, Id, Key attribute, MaxLength attribute, data transfer object, DTO, ProductDto, same contract, OnlineShop.ServiceDefaults
3.2.2 Displaying the DTO information in the UI
The section explains why the online shop UI remains independent of its database and describes the changes that make it display products instead of sample weather data.
- Database-agnostic UI boundary: Explain how a separate DTO lets the presentation and infrastructure layers exchange data without depending on each other’s implementation details.
Why it matters: This separation lets the same UI serve as the starting point for different database implementations. - Product display UI changes: Describe the OnlineShop.Web changes that replace the sample weather UI with a product display, including the API client, its DI registration, the home page, and obsolete pages and links.
Why it matters: These changes provide the product-facing UI that the chapter’s database alternatives can share.
Key terms: database-agnostic, separation of concerns, DTO, infrastructure layer, presentation layer, OnlineShop.Web, ProductsApiClient, builder.Services.AddHttpClient(), Home.razor, NavMenu.razor
3.3 Hosting a SQL Server component
This section shows how to host a SQL Server container and database in Aspire, configure their names and connection settings, preserve development data, and make the database available to a service.
- SQL Server host setup: Describe how the Aspire host adds a SQL Server container and how its administrator password and port are chosen by default or configured explicitly.
Why it matters: These are the host-side choices that determine how the development SQL Server starts. - Database creation and naming: Explain what AddDatabase() does in the Aspire version described here and distinguish the database resource name from the database it can reference.
Why it matters: It clarifies whether registration creates a database and which name other services use to identify its resource. - Container lifetime and data: Justify making the development SQL Server container's lifetime persistent and distinguish that choice from the recommended production database approach.
Why it matters: A restarted development setup should not unexpectedly discard its database data. - Service database dependency: Describe how the host gives a service its database reference and delays that service until the database is ready.
Why it matters: The service needs both a way to find the database and a ready database when it starts.
Key terms: Aspire.Hosting.SqlServer, AppHost.cs, AddSqlServer(), sa, AddParameter(), AddDatabase(), database resource, service discovery, sqldb, master
3.3.1 Consuming a SQL Server integration
Shows how an Aspire-hosted API uses the ADO.NET SQL Server integration to connect to a database, work with product data, and return it through an endpoint.
- SQL Server client registration: Explain how the consuming API registers the ADO.NET SQL Server client and obtains a connection without constructing its own connection string.
Why it matters: The resource name connects the API's client registration to the connection details supplied by the Aspire host. - Product database example flow: Trace how the example uses the SQL client to create a Shop database and product table, populate the table if empty, and return queried data from an API endpoint.
Why it matters: The example connects client registration to a concrete database setup and product-data retrieval workflow. - Database access placement: Distinguish the example's direct database access in an API endpoint from the service-layer approach described for a real application.
Why it matters: It keeps a convenient teaching example from being mistaken for the recommended application structure.
Key terms: Aspire.Microsoft.Data.SqlClient, SqlConnection, dependency injection, connection string, ADO.NET, Shop, USE Shop, products, API endpoint, service layer
3.3.2 Using Entity Framework
This section shows how the API service uses Entity Framework with its existing Aspire-hosted SQL Server, from registering a DbContext to creating and querying the database.
- Entity Framework client switch: Explain that using Entity Framework changes the API service’s database client, not the SQL Server instance hosted by Aspire, and identify the NuGet package added to the API project.
Why it matters: It separates a change in the API’s data-access approach from a change in hosted infrastructure. - DbContext registration and connection: Describe how ProductsDbContext represents the products database, is registered for dependency injection, and uses the Aspire host’s connection string through the sqldb connection name.
Why it matters: It connects the API’s Entity Framework context to the database already configured by Aspire. - Automatic database creation: Explain what calling EnsureCreated() on the context’s Database property does and why the example does not present it as the right choice for every database.
Why it matters: It clarifies both the convenience and the stated limit of the example’s database setup. - Query execution and results: Explain what ToArray() or ToArrayAsync() does when the API endpoint retrieves products.
Why it matters: It identifies the point at which the example’s product query actually runs and produces endpoint data.
Key terms: Entity Framework, Aspire.Microsoft.EntityFrameworkCore.SqlServer, OnlineShop.ApiService, DbContext, ProductsDbContext, DI, sqldb, connection string, EnsureCreated(), Database
3.3.3 Integrating with Azure SQL Server
This section explains how to register Azure SQL Server in an Aspire host, how that resource behaves locally and in Azure, and when existing SQL Server clients can use it.
- Azure SQL resource registration: Describe how to register Azure SQL Server in an Aspire host using Aspire.Hosting.Azure.Sql and AddAzureSqlServer(), then register its database with AddDatabase().
Why it matters: It distinguishes registering the Azure SQL Server resource from registering a database on it. - Local and Azure behavior: Explain why the default AddAzureSqlServer() setup is suited to Azure deployment but does not provide a working local Docker database.
Why it matters: It prevents mistaking Azure resource provisioning for an automatically available local database. - SQL Server client compatibility: State when the previously used SQL Server client libraries work with Azure SQL Server integration or a database registered through AddConnectionString().
Why it matters: Changing how the database is registered need not mean changing SQL Server client libraries, but the connection must still be wired correctly.
Key terms: Aspire.Hosting.Azure.Sql, AddAzureSqlServer(), AddDatabase(), Docker container, managed Azure SQL Server instance, resource group, SQL Server client libraries, AddConnectionString(), connection string resource, reference
3.4 Hosting an Oracle component
This section explains how to host and consume an Oracle database in Aspire, why its container should persist during local development, and how the same client registration can connect to an existing Oracle database.
- Oracle host registration: Describe how to host an Oracle database in Aspire: install Aspire.Hosting.Oracle in the host project, then create a database server container and database reference.
Why it matters: This is the host-side setup needed to run Oracle with the application. - Persistent Oracle container lifetime: Explain why setting a persistent lifetime is especially useful for an Oracle container during local development.
Why it matters: Persistence makes repeated local runs and debugging less time-consuming. - Oracle Entity Framework client: Describe the consuming service's Oracle client setup and how application data-access code compares with other database providers.
Why it matters: It separates Oracle-specific connection setup from largely familiar data-access code. - Existing Oracle database connections: Explain when the Oracle client registration can work with an existing database supplied through AddConnectionString().
Why it matters: The same client-side approach is not limited to an Oracle container hosted by Aspire.
Key terms: Aspire.Hosting.Oracle, database server container, database reference, persistent lifetime, Oracle container, Aspire.Oracle.EntityFrameworkCore, DbContext, Entity Framework, LINQ, AddConnectionString()
3.5 Hosting a PostgreSQL component
This section shows how to host PostgreSQL in Aspire, connect to it through raw SQL or Entity Framework, and obtain its connection string.
- PostgreSQL host registration: Describe how Aspire registers a PostgreSQL server and database, and distinguish what AddDatabase() does in the current Aspire version versus version 8.
Why it matters: The distinction prevents you from assuming an older Aspire version creates the database for you. - PostgreSQL client approaches: Distinguish the raw-SQL and Entity Framework options for consuming PostgreSQL, including what the registered NpgsqlDataSource provides and why Entity Framework uses LINQ.
Why it matters: You can choose between direct PostgreSQL access and an Entity Framework context without confusing their roles. - Database connection string resolution: Explain how a hosted service obtains its database connection string with an Aspire-specific client package and where to find it when using another library.
Why it matters: A service can connect even if it uses a database client library without an Aspire-specific integration.
Key terms: Aspire.Hosting.PostgreSQL, AddPostgres(), AddDatabase(), Aspire.Npgsql, NpgsqlDataSource, Aspire.Npgsql.EntityFrameworkCore.PostgreSQL, DB context, LINQ, connection string, database reference
3.6 Introduction to NoSQL
Defines NoSQL, introduces four ways NoSQL databases organize data, and explains which kinds of problems suit each.
- Meaning and diversity of NoSQL: Explain that NoSQL refers to storage outside the traditional relational structure, not necessarily to databases that never use SQL. Describe why the name does not identify one shared database type or standard.
Why it matters: The term NoSQL alone does not tell you how a database stores data or how you will query it. - Four NoSQL storage models: Distinguish document, key-value, graph, and column-family stores by how each organizes data.
Why it matters: The storage model gives you a more useful description of a database than the broad NoSQL label. - Problem fit by storage model: Explain the section’s examples of when key-value, column-family, graph, and document stores are useful, rather than assuming a relational database suits every problem.
Why it matters: Choosing a storage model starts with the kind of data and access the application needs.
Key terms: NoSQL, relational structure, SQL, document store, key-value store, graph database, column-family store, distributed cache, data warehousing, connection maps
3.6.1 Introduction to MongoDB
Introduces MongoDB’s document model and explains when it may be useful instead of a relational database, including its tradeoffs for relationships and application objects.
- MongoDB document model: Describe how MongoDB stores data in BSON documents grouped into collections rather than SQL tables and rows, and how a document can hold related data such as a product and its reviews.
Why it matters: This model explains why product reviews are a plausible fit for MongoDB. - Document store tradeoffs: Explain why MongoDB can suit flexible or rapidly evolving applications while being difficult to use when relationships between separate entities must be tracked.
Why it matters: Choosing a database depends on both the flexibility an application needs and the relationships it must track. - Object mapping advantage: Explain why a document store can reduce the object-relational impedance mismatch compared with mapping relational tables to C# classes.
Why it matters: The shape of stored data affects how much translation application code needs.
Key terms: MongoDB, NoSQL, document store, BSON, collections, documents, relationships, foreign-key constraints, iterative development, real-time analytics
3.6.2 Hosting a MongoDB component
Shows how to register a MongoDB container and make its database available to an Aspire-hosted service.
- MongoDB hosting and service reference: Describe how to host MongoDB in Aspire and connect a service to its database reference.
Why it matters: This is the setup needed to make a MongoDB database available to a service in the Aspire app.
Key terms: Aspire.Hosting.MongoDB, AppHost.cs, MongoDB server instance, database reference, WithReference()
3.6.3 Working with a MongoDB client
This section shows how an Aspire-hosted service connects to MongoDB, represents documents, seeds an empty collection, and exposes its data through an API endpoint.
- MongoDB client registration: Explain how a hosted service registers a MongoDB client and obtains its connection configuration through Aspire.
Why it matters: It explains how the service gets a usable MongoDB client without manually wiring its connection string. - MongoDB document model: Describe the class used to represent a MongoDB BSON document and how its identifier is represented.
Why it matters: The document class gives the MongoDB records used in the example a representation in C#. - Product review data flow: Trace how the example obtains a MongoDB collection, seeds it when empty, and makes its product reviews available through an API endpoint.
Why it matters: It connects client registration to the example's database setup, initial data, and readable API.
Key terms: Aspire.MongoDB.Driver, AddMongoDBClient(), database reference, connection string, MongoDB C# Driver, BSON document, Id, ObjectId, ProductReviewsDocument, IMongoClient
3.6.4 Other NoSQL components
This section introduces Azure Cosmos DB as a globally distributed, multimodel NoSQL service that Aspire can emulate locally.
- Global distribution and replication: Explain how Cosmos DB’s distribution and replication across Azure regions support availability and low-latency access.
Why it matters: This explains what the section means by calling Cosmos DB globally distributed. - Data models and API choices: Describe how Cosmos DB supports multiple NoSQL data models and lets developers choose APIs for different uses, giving examples from the section.
Why it matters: The range of models and APIs explains why the section describes Cosmos DB as versatile. - Local Cosmos DB emulation: Distinguish Cosmos DB’s Azure production hosting from the local emulated instance that Aspire can host in a Docker container.
Why it matters: The emulator makes this Azure service available for local development with Aspire.
Key terms: globally distributed, data replication, Azure regions, active-active, active-passive, multimodel, data models, API-agnostic, SQL API, MongoDB API
3.6.5 Hosting a Cosmos DB component
The section shows how to register a Cosmos DB component in an Aspire host, choose between Azure and an emulator, and reference it from a service.
- Cosmos DB host configuration: Describe how to enable and register a Cosmos DB component in the Aspire host, and distinguish connecting to Azure from using an emulator for local debugging.
Why it matters: This distinguishes a local Cosmos DB setup from one that uses a real Azure instance. - Service reference to Cosmos DB: Explain how a service that uses the hosted Cosmos DB component is given a reference to it.
Why it matters: Registering the component on the host is separate from making it available to a particular service.
Key terms: Aspire.Hosting .Azure.CosmosDB, AppHost.cs, AddAzureCosmosDB(), emulated mode, Cosmos DB component variable, WithReference()
3.6.6 Connecting to Cosmos DB
This section explains how an Aspire-hosted service registers a Cosmos DB client and names an Entity Framework alternative.
- Cosmos DB client registration: Explain how a service hosted by Aspire registers a Cosmos DB client and why the registration name must match the name used in the host app.
Why it matters: Matching the host app’s name lets the service obtain its Cosmos DB connection string automatically. - Entity Framework Cosmos option: State how the section says an Aspire-hosted service can also interact with Cosmos DB through Entity Framework.
Why it matters: The section identifies an Entity Framework option alongside the Aspire-specific Cosmos DB client.
Key terms: Aspire.Microsoft.Azure.Cosmos, AddAzureCosmosClient(), CosmosClient, connection string, Entity Framework, Aspire.Microsoft.EntityFrameworkCore.Cosmos
3.7 Azure Storage integration
Introduces Azure Storage accounts and distinguishes their table, blob, and queue storage services by what each stores or does.
- Azure Storage account structure: Explain that an Azure Storage account is a data-storage service containing several subservices, and that the Azure-specific storage services discussed here can be emulated locally.
Why it matters: The account is the common context for the different storage services introduced here. - Storage subservice roles: Distinguish Table Storage as flat, unrelated NoSQL tables suited to reference data; Blob Storage as cloud file storage; and Queue Storage as a way for services to exchange messages rather than a database.
Why it matters: Choosing among these services starts with recognizing whether the application needs reference data, files, or message exchange.
Key terms: Azure Storage account, subservices, emulated locally, Table Storage, NoSQL, reference data, Blob Storage, Queue Storage, message broker
3.7.1 Hosting Azure Storage components
This subsection shows how an Aspire host provides Azure Table Storage, either through an emulator or real Azure resources, and passes its reference to a service.
- Azure Table Storage hosting: Explain why Aspire uses a common Azure Storage component and describe the stated steps for hosting Table Storage, including the emulator and real-resource options.
Why it matters: This distinguishes local emulated Table Storage from connecting the application to real Azure storage resources. - Table Storage service reference: Describe how the hosted Table Storage component is made available to the service that will use it.
Why it matters: Hosting the storage component is not the same as giving a service a reference to it.
Key terms: storage account, Aspire.Hosting.Azure .Storage, AppHost.cs, RunAsEmulator(), AddAzureStorage(), AddTables(), Table Storage reference, service
3.7.2 Interacting with Azure Table Storage
This section shows how an Aspire-hosted service connects to Azure Table Storage, models its entities, seeds a table, and exposes its data through an API.
- Table Storage service dependency: Describe what an Aspire-hosted service needs to interact with Table Storage: the Aspire.Azure.Data.Tables NuGet package and dependency registration in Program.cs.
Why it matters: The service needs its Table Storage dependency registered before it can use the table client. - Required table entity columns: Explain the roles of PartitionKey, RowKey, ETag, and Timestamp in a Table Storage entity.
Why it matters: These columns give a product metadata entity the identifiers and metadata the section requires for Table Storage. - Table seeding and retrieval: Trace the described flow for seeding Table Storage and making its data available through an API endpoint.
Why it matters: The flow prepares initial data without reseeding a nonempty table and makes that data available to callers.
Key terms: Aspire.Azure.Data.Tables, Program.cs, PartitionKey, RowKey, ETag, Timestamp, TableServiceClient, seed data, API endpoint, HTTP response
3.7.3 Integrating with Azure Blob Storage
This section shows how an Aspire application hosts emulated Azure Blob Storage, seeds a CSV file of product specifications, and makes the file downloadable through an API endpoint.
- Blob Storage integration setup: Explain that Blob Storage holds files such as downloadable product specifications, and distinguish the package used to host an emulated instance from the package installed in the service that accesses it.
Why it matters: Separating hosting from service access clarifies where each integration package belongs. - Product specifications CSV seeding: Describe how the initial product specifications are stored as a CSV file in the products blob container, including what happens when the container or file already exists.
Why it matters: The existence checks prevent initial seeding from replacing a product-specifications file that is already there. - CSV stream and download: Explain why the CSV writer is flushed and the memory stream reset before the blob client reads it, and state how the example exposes the resulting file.
Why it matters: Preparing the stream for reading connects the generated CSV data to the downloadable blob.
Key terms: Blob Storage, Aspire.Hosting.Azure.Storage, Aspire.Azure.Storage.Blobs, emulated mode, products, product-specs.csv, CsvHelper, seed, CSV file, memory stream
3.8 Summary
Where this is used later
- Managing the Redis cache (chapter 7) · connecting Aspire to an existing data resource
- Reconfiguring the infrastructure components (chapter 10) · Connecting Aspire to an existing database
- Adding order-processing functionality (chapter 7) · Working with the SQL data model.
- Running environment-specific services (chapter 9) · Environment-specific services build on the distinction between a development container and a production database.
- Managing database migrations (chapter 9) · Use of Entity Framework with the SQL database
- Overview of distributed cache and lock (chapter 7) · Provides context for the key-value model when discussing distributed caches.
- Working with Azure Queue Storage (chapter 7) · Introduces Azure Storage integrations.
- Hosting an emulated Azure Queue Storage component (chapter 7) · Hosting Azure Storage components in Aspire.
Concepts explained in this chapter
- data transfer objectA data transfer object is a data-only structure that carries selected values across application or service boundaries.
- AddDatabaseAddDatabase is a .NET Aspire hosting API method that registers or creates a database associated with a database server resource.
- NoSQL databaseA non-relational database system that stores and accesses data using models other than relational tables and does not rely primarily on SQL.
- MongoDBMongoDB is a document-oriented NoSQL database management system.
- connection stringA structured configuration value specifying how an application connects to a database.
- persistent lifetimeA persistent lifetime is a resource-lifecycle setting that preserves a resource instance for reuse across application runs.
- waitforWaitFor() is an Aspire API method that delays a resource's startup until another resource is ready.
- withreferenceWithReference() is an Aspire API method that adds a reference from one application resource to another.
- Aspire integration libraryA reusable library that connects an application framework to an external service or infrastructure component.
- EnsureCreatedEnsureCreated is an Entity Framework method that creates the database if it does not already exist.
- ConnectionStrings sectionA named section of .NET application settings that holds database connection strings.
- Azure Storage QueuesAn Azure service that stores messages in queues for asynchronous exchange between services.
These guides are generated from the text of Manning books by Manning's knowledge graph and link to the sections they draw on. The full books are available on liveBook and at manning.com.
