|
1 | 1 | ---
|
2 | 2 | title: Seed data in a database using .NET Aspire
|
3 | 3 | description: Learn about how to seed database data in .NET Aspire
|
4 |
| -ms.date: 08/12/2024 |
| 4 | +ms.date: 05/14/2025 |
5 | 5 | ms.topic: how-to
|
6 | 6 | ---
|
7 | 7 |
|
8 | 8 | # Seed data in a database using .NET Aspire
|
9 | 9 |
|
10 |
| -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 for common platforms such as SQL Server, PostgreSQL and MySQL. |
| 10 | +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. |
11 | 11 |
|
12 | 12 | ## When to seed data
|
13 | 13 |
|
14 |
| -Seeding data pre-populates database tables with rows of data so they're ready for testing via your app. You may want to seed data for the following scenarios: |
| 14 | +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: |
15 | 15 |
|
16 |
| -- Manually develop and test different features of your app against a meaningful set of data, such as a product catalog or list of customers. |
17 |
| -- Run test suites to verify that features behave a specific way with a given set of data. |
| 16 | +- 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. |
| 17 | +- You want to run test suites to verify that features behave correctly with a given set of data. |
18 | 18 |
|
19 |
| -Manually seeding data is tedious and time consuming, so you should automate the process when possible. Use volumes to run database scripts for .NET Aspire projects during startup. You can also seed your database using tools like Entity Framework Core, which handles many underlying concerns for you. |
| 19 | +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. |
20 | 20 |
|
21 | 21 | ## Understand containerized databases
|
22 | 22 |
|
23 | 23 | By default, .NET Aspire database integrations rely on containerized databases, which create the following challenges when trying to seed data:
|
24 | 24 |
|
25 |
| -- .NET Aspire destroys and recreates containers every time the app restarts, which means by default you have to re-seed your database every time the app restarts. |
| 25 | +- 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. |
26 | 26 | - 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.
|
27 |
| -- Even if a default database exists, it most likely will not have the desired name or schema for your specific app. |
| 27 | +- Even if a default database exists, it most likely won't have the desired name or schema for your specific app. |
28 | 28 |
|
29 |
| -.NET Aspire enables you to resolve these challenges using volumes and a few configurations to seed data effectively. |
| 29 | +.NET Aspire enables you to resolve these challenges using volumes, bind mounts, and a few configurations to seed data effectively. |
30 | 30 |
|
31 |
| -## Seed data using volumes and SQL scripts |
| 31 | +> [!TIP] |
| 32 | +> 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. |
32 | 33 |
|
33 |
| -Volumes are the recommended way to automatically seed containerized databases when using SQL scripts. Volumes can store data for multiple containers at a time, offer high performance and are easy to back up or migrate. With .NET Aspire, you configure a volume for each resource container using the <xref:Aspire.Hosting.ContainerResourceBuilderExtensions.WithBindMount%2A?displayProperty=nameWithType> method, which accepts three parameters: |
34 |
| - |
35 |
| -- **Source**: The source path of the volume mount, which is the physical location on your host. |
36 |
| -- **Target**: The target path in the container of the data you want to persist. |
37 |
| - |
38 |
| -Consider the following volume configuration code from a _:::no-loc text="Program.cs":::_ file in a sample **AppHost** project: |
39 |
| - |
40 |
| -```csharp |
41 |
| -var todosDbName = "Todos"; |
42 |
| -var todosDb = builder.AddPostgres("postgres") |
43 |
| - .WithEnvironment("POSTGRES_DB", todosDbName) |
44 |
| - .WithBindMount( |
45 |
| - "../DatabaseContainers.ApiService/data/postgres", |
46 |
| - "/docker-entrypoint-initdb.d") |
47 |
| - .AddDatabase(todosDbName); |
48 |
| -``` |
49 |
| - |
50 |
| -In this example, the `.WithBindMount` method parameters configure the following: |
51 |
| - |
52 |
| -- `../DatabaseContainers.ApiService/data/postgres` sets a path to the SQL script in your local project that you want to run in the container to seed data. |
53 |
| -- `/docker-entrypoint-initdb.d` sets the path to an entry point in the container so your script will be run during container startup. |
54 |
| - |
55 |
| -The referenced SQL script located at `../DatabaseContainers.ApiService/data/postgres` creates and seeds a `Todos` table: |
56 |
| - |
57 |
| -```sql |
58 |
| --- Postgres init script |
| 34 | +> [!NOTE] |
| 35 | +> Visit the [Database Container Sample App](https://github.com/dotnet/aspire-samples/blob/main/samples/DatabaseContainers/DatabaseContainers.AppHost/Program.cs) to view the full project and file structure for each database option. |
59 | 36 |
|
60 |
| --- Create the Todos table |
61 |
| -CREATE TABLE IF NOT EXISTS Todos |
62 |
| -( |
63 |
| - Id SERIAL PRIMARY KEY, |
64 |
| - Title text UNIQUE NOT NULL, |
65 |
| - IsComplete boolean NOT NULL DEFAULT false |
66 |
| -); |
| 37 | +## Seed data using SQL scripts |
67 | 38 |
|
68 |
| --- Insert some sample data into the Todos table |
69 |
| -INSERT INTO Todos (Title, IsComplete) |
70 |
| -VALUES |
71 |
| - ('Give the dog a bath', false), |
72 |
| - ('Wash the dishes', false), |
73 |
| - ('Do the groceries', false) |
74 |
| -ON CONFLICT DO NOTHING; |
75 |
| -``` |
| 39 | +In .NET Aspire 9.2, the recommended method for executing database seeding scripts depends on the database server you use: |
76 | 40 |
|
77 |
| -The script runs during startup every time a new container instance is created. |
| 41 | +### [SQL Server](#tab/sql-server) |
78 | 42 |
|
79 |
| -## Database seeding examples |
| 43 | +In .NET Aspire 9.2 and later versions, you can use the <xref:Aspire.Hosting.SqlServerBuilderExtensions.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. |
80 | 44 |
|
81 |
| -The following examples demonstrate how to seed data using SQL scripts and configurations applied using the `.WithBindMount` method for different database technologies: |
| 45 | +The following code is an example T-SQL script that creates and populates an address book database: |
82 | 46 |
|
83 |
| -> [!NOTE] |
84 |
| -> Visit the [Database Container Sample App](https://github.com/dotnet/aspire-samples/blob/main/samples/DatabaseContainers/DatabaseContainers.AppHost/Program.cs) to view the full project and file structure for each database option. |
| 47 | +:::code source="~/aspire-samples/samples/DatabaseContainers/DatabaseContainers.ApiService/data/sqlserver/init.sql" ::: |
85 | 48 |
|
86 |
| -### [SQL Server](#tab/sql-server) |
| 49 | +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: |
87 | 50 |
|
88 |
| -The configuration code in the **.AppHost** _:::no-loc text="Program.cs":::_ file mounts the required database files and folders and configures an entrypoint so that they run during startup. |
| 51 | +:::code language="xml" source="~/aspire-samples/samples/DatabaseContainers/DatabaseContainers.AppHost/DatabaseContainers.AppHost.csproj" range="13-17" ::: |
89 | 52 |
|
90 |
| -:::code source="~/aspire-samples/samples/DatabaseContainers/DatabaseContainers.AppHost/Program.cs" range="37-49" ::: |
| 53 | +Adjust the `Include` parameter to match the path to your SQL script in the project. |
91 | 54 |
|
92 |
| -The _entrypoint.sh_ script lives in the mounted `./sqlserverconfig` project folder and runs when the container starts. The script launches SQL Server and checks that it's running. |
| 55 | +Next, in the app host's *Program.cs* file, create the database and run the creation script: |
93 | 56 |
|
94 |
| -:::code source="~/aspire-samples/samples/DatabaseContainers/DatabaseContainers.AppHost/sqlserverconfig/entrypoint.sh" ::: |
| 57 | +:::code source="~/aspire-samples/samples/DatabaseContainers/DatabaseContainers.AppHost/Program.cs" range="40-49" ::: |
95 | 58 |
|
96 |
| -The _init.sql_ SQL script that lives in the mounted `../DatabaseContainers.ApiService/data/sqlserver` project folder creates the database and tables. |
| 59 | +This code: |
97 | 60 |
|
98 |
| -:::code source="~/aspire-samples/samples/DatabaseContainers/DatabaseContainers.ApiService/data/sqlserver/init.sql" ::: |
| 61 | +- Create a SQL Server container by calling `builder.AddSqlServer()`. |
| 62 | +- Ensures that data is persisted across debugging sessions by calling `WithDataVolume()` and `WithLifetime(ContainerLifetime.Persistent)`. |
| 63 | +- Obtains the path to the T-SQL script in the output folder. |
| 64 | +- Calls `WithCreationScript()` to create and seed the database. |
99 | 65 |
|
100 | 66 | ### [PostgreSQL](#tab/postgresql)
|
101 | 67 |
|
102 |
| -Configuration code in the **.AppHost** project: |
| 68 | +In .NET Aspire 9.2, the `WithCreationScript()` method isn't supported for the PostgreSQL integration. Instead, you must use a bind mount and deploy the setup SQL script to it, so that the data is seeded when the container initializes the database. |
103 | 69 |
|
104 |
| -:::code source="~/aspire-samples/samples/DatabaseContainers/DatabaseContainers.AppHost/Program.cs" range="3-15" ::: |
105 |
| - |
106 |
| -Corresponding SQL script included in the app: |
| 70 | +The following code is an example PostgreSQL script that creates and populates a to do list database: |
107 | 71 |
|
108 | 72 | :::code source="~/aspire-samples/samples/DatabaseContainers/DatabaseContainers.ApiService/data/postgres/init.sql" :::
|
109 | 73 |
|
110 |
| -### [MySQL](#tab/mysql) |
| 74 | +In the app host's *Program.cs* file, create the database and mount the folder that contains the SQL script as a bind mount: |
| 75 | + |
| 76 | +:::code source="~/aspire-samples/samples/DatabaseContainers/DatabaseContainers.AppHost/Program.cs" range="3-19" ::: |
111 | 77 |
|
112 |
| -Configuration code in the **.AppHost** project: |
| 78 | +### [MySQL](#tab/mysql) |
113 | 79 |
|
114 |
| -:::code source="~/aspire-samples/samples/DatabaseContainers/DatabaseContainers.AppHost/Program.cs" range="20-32" ::: |
| 80 | +In .NET Aspire 9.2, the `WithCreationScript()` method isn't supported for the MySQL integration. Instead, you must use a bind mount and deploy the setup SQL script to it, so that the data is seeded when the container initializes the database. |
115 | 81 |
|
116 |
| -Corresponding SQL script included in the app: |
| 82 | +The following code is an example MySQL script that creates and populates a product catalog database: |
117 | 83 |
|
118 | 84 | :::code source="~/aspire-samples/samples/DatabaseContainers/DatabaseContainers.ApiService/data/mysql/init.sql" :::
|
119 | 85 |
|
| 86 | +In the app host's *Program.cs* file, create the database and mount the folder that contains the SQL script as a bind mount: |
| 87 | + |
| 88 | +:::code source="~/aspire-samples/samples/DatabaseContainers/DatabaseContainers.AppHost/Program.cs" range="21-36" ::: |
| 89 | + |
120 | 90 | ---
|
121 | 91 |
|
122 |
| -## Seed data using Entity Framework Core |
| 92 | +## Seed data using EF Core |
123 | 93 |
|
124 |
| -You can also seed data in .NET Aspire projects using Entity Framework Core by explicitly running migrations during startup. Entity Framework Core handles underlying database connections and schema creation for you, which eliminates the need to use volumes or run SQL scripts during container startup. |
| 94 | +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. |
125 | 95 |
|
126 | 96 | > [!IMPORTANT]
|
127 | 97 | > These types of configurations should only be done during development, so make sure to add a conditional that checks your current environment context.
|
@@ -197,6 +167,7 @@ if (app.Environment.IsDevelopment())
|
197 | 167 |
|
198 | 168 | Database seeding is useful in a variety of app development scenarios. Try combining these techniques with the resource implementations demonstrated in the following tutorials:
|
199 | 169 |
|
200 |
| -- [Tutorial: Connect an ASP.NET Core app to SQL Server using .NET Aspire and Entity Framework Core](../database/sql-server-integrations.md) |
| 170 | +- [Tutorial: Connect an ASP.NET Core app to SQL Server using .NET Aspire and Entity Framework Core](sql-server-integrations.md) |
| 171 | +- [Tutorial: Apply Entity Framework Core migrations in .NET Aspire](ef-core-migrations.md) |
201 | 172 | - [Tutorial: Connect an ASP.NET Core app to .NET Aspire storage integrations](../storage/azure-storage-integrations.md)
|
202 | 173 | - [.NET Aspire orchestration overview](../fundamentals/app-host-overview.md)
|
0 commit comments