Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
In this article, you learn how to configure .NET Aspire projects to seed data in a database during app startup. .NET Aspire enables you to seed data using database scripts or Entity Framework Core (EF Core) for common platforms such as SQL Server, PostgreSQL, and MySQL.
When to seed data
Seeding data pre-populates database tables with rows of data so they're ready for testing your app. You may want to seed data for the following scenarios:
- You want to develop and test different features of your app manually against a meaningful set of data, such as a product catalog or a list of customers.
- You want to run test suites to verify that features behave correctly with a given set of data.
Manually seeding data is tedious and time consuming, so you should automate the process whenever possible. You can seed your database either by running database scripts for .NET Aspire projects during startup or by using tools like EF Core, which handles many underlying concerns for you.
Understand containerized databases
By default, .NET Aspire database integrations rely on containerized databases, which create the following challenges when trying to seed data:
- By default, .NET Aspire destroys and recreates containers every time the app restarts, which means you have to re-seed your database on each run.
- Depending on your selected database technology, the new container instance may or may not create a default database, which means you might also have to create the database itself.
- Even if a default database exists, it most likely won't have the desired name or schema for your specific app.
.NET Aspire enables you to resolve these challenges using volumes, bind mounts, and a few configurations to seed data effectively.
Tip
Container hosts like Docker and Podman support volumes and bind mounts, both of which provide locations for data that persist when a container restarts. Volumes are the recommended solution, because they offer better performance, portability, and security. The container host creates and remains in control of volumes. Each volume can store data for multiple containers. Bind mounts have relatively limited functionality in comparison but enable you to access the data from the host machine.
Note
Visit the Database Container Sample App to view the full project and file structure for each database option.
Seed data using SQL scripts
In .NET Aspire 9.2, the recommended method for executing database seeding scripts depends on the database server you use:
In .NET Aspire 9.2 and later versions, you can use the WithCreationScript method to ensure a T-SQL script is run when the database is created. Add SQL code to this script that creates and populates the database, the necessary tables, and other database objects.
The following code is an example T-SQL script that creates and populates an address book database:
-- SQL Server init script
-- Create the AddressBook database
IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = N'AddressBook')
BEGIN
CREATE DATABASE AddressBook;
END;
GO
USE AddressBook;
GO
-- Create the Contacts table
IF OBJECT_ID(N'Contacts', N'U') IS NULL
BEGIN
CREATE TABLE Contacts
(
Id INT PRIMARY KEY IDENTITY(1,1) ,
FirstName VARCHAR(255) NOT NULL,
LastName VARCHAR(255) NOT NULL,
Email VARCHAR(255) NULL,
Phone VARCHAR(255) NULL
);
END;
GO
-- Ensure that either the Email or Phone column is populated
IF OBJECT_ID(N'chk_Contacts_Email_Phone', N'C') IS NULL
BEGIN
ALTER TABLE Contacts
ADD CONSTRAINT chk_Contacts_Email_Phone CHECK
(
Email IS NOT NULL OR Phone IS NOT NULL
);
END;
GO
-- Insert some sample data into the Contacts table
IF (SELECT COUNT(*) FROM Contacts) = 0
BEGIN
INSERT INTO Contacts (FirstName, LastName, Email, Phone)
VALUES
('John', 'Doe', 'john.doe@example.com', '555-123-4567'),
('Jane', 'Doe', 'jane.doe@example.com', '555-234-5678');
END;
GO
You must ensure that this script is copied to the app host's output directory, so that .NET Aspire can execute it. Add the following XML to your .csproj file:
<ItemGroup>
<None Include="..\DatabaseContainers.ApiService\data\sqlserver\init.sql" Link="init.sql">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
Adjust the Include
parameter to match the path to your SQL script in the project.
Next, in the app host's AppHost.cs (or Program.cs) file, create the database and run the creation script:
var sqlserver = builder.AddSqlServer("sqlserver")
// Configure the container to store data in a volume so that it persists across instances.
.WithDataVolume()
// Keep the container running between app host sessions.
.WithLifetime(ContainerLifetime.Persistent);
// Add the database to the application model so that it can be referenced by other resources.
var initScriptPath = Path.Join(Path.GetDirectoryName(typeof(Program).Assembly.Location), "init.sql");
var addressBookDb = sqlserver.AddDatabase("AddressBook")
.WithCreationScript(File.ReadAllText(initScriptPath));
This code:
- Create a SQL Server container by calling
builder.AddSqlServer()
. - Ensures that data is persisted across debugging sessions by calling
WithDataVolume()
andWithLifetime(ContainerLifetime.Persistent)
. - Obtains the path to the T-SQL script in the output folder.
- Calls
WithCreationScript()
to create and seed the database.
Seed data using EF Core
You can also seed data in .NET Aspire projects using EF Core by explicitly running migrations during startup. EF Core handles underlying database connections and schema creation for you, which eliminates the need to use volumes or run SQL scripts during container startup.
Important
These types of configurations should only be done during development, so make sure to add a conditional that checks your current environment context.
Add the following code to the _Program.cs file of your API Service project.
// Register DbContext class
builder.AddSqlServerDbContext<TicketContext>("sqldata");
var app = builder.Build();
app.MapDefaultEndpoints();
if (app.Environment.IsDevelopment())
{
// Retrieve an instance of the DbContext class and manually run migrations during startup
using (var scope = app.Services.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<TicketContext>();
context.Database.Migrate();
}
}
Next steps
Database seeding is useful in a variety of app development scenarios. Try combining these techniques with the resource implementations demonstrated in the following tutorials:
.NET Aspire