EntityFramework.Docs icon indicating copy to clipboard operation
EntityFramework.Docs copied to clipboard

Documentation is unclear about applying data seeding with UseSeeding for non-local environments

Open sander1095 opened this issue 10 months ago • 4 comments

Type of issue

Missing information

Description

I'm currently working with the new UseSeeding feature from EF Core 9 to apply seed data to the database.

However, the docs are unclear about how this should be used for non-local environments in a "good" way.

The previous "recommended way" was to use HasData, which puts the seed data in your migrations. Next, you can generate a SQL script based on your migrations, which includes the seed data from HasData.

UseSeeding only runs in the following scenario's, which the docs discourage from using in non-local environments:

  • When EnsureCreated() is called
  • When Migrate() is called
  • When dotnet ef database update is called.

My question is: What is the recommended way to combine the recommended way of applying migrations (generating a SQL script based on your migrations) with the recommended way of applying seed data (UseSeeding) for non-local environments?

My guess is that we're not supposed to use UseSeeding in non-local environments. If that is the case, the documentation should get mention this 🙂

For some more context, check my question on StackOverflow: https://stackoverflow.com/q/79454619/3013479

Page URL

https://learn.microsoft.com/en-us/ef/core/modeling/data-seeding#use-seeding-method

Content source URL

https://github.com/dotnet/EntityFramework.Docs/blob/main/entity-framework/core/modeling/data-seeding.md

Document Version Independent Id

822e8923-2647-f573-0c74-66af903776d8

Article author

@AndriySvyryd

sander1095 avatar Feb 20 '25 13:02 sander1095

/cc @AndriySvyryd

roji avatar Feb 20 '25 17:02 roji

If you are using a SQL script generated from migrations, then indeed UseSeeding wouldn't be appropriate.

But starting with EF 9 calling Migrate() is no longer considered a bad practice for non-local environments. Also, migration bundles is a good alternative to pure scripts and it supports the new seeding pattern.

AndriySvyryd avatar Feb 25 '25 00:02 AndriySvyryd

Hi @AndriySvyryd , thanks for your reply.

Let me start by saying that I think the docs should be updated based on your reply, especially because there is no way of knowing that migration bundles work together with UseSeeding:

  1. Starting with EF Core 9, Migrate may be considered as a valid option for non-local environments, but others are still preferred
  2. If you want to use UseSeeding in non-local environments, these are your options: (options here, including efbundle)
  3. The link to "recommended methods" in the docs should be updated to migration bundles, as they support everything that SQL scripts do, including UseSeeding().
  4. Perhaps the migration bundles part in the docs should mention it supports UseSeeding, which the SQL Scripts do not.

Personally, I do not believe that Migrate() is a valid approach, as infrastructure deployments (like database schema changes) should be decoupled from application deployments. If Migrate() fails and the user isn't using a zero-downtime deployment strategy, you end up with an application that's fully down or unreliable. Also, Migrate() is still unreliable for sqlite, as the locking mechanism can cause issues when applying migrations fail, requiring manual intervention.

This doesn't mean that people can't start using Migrate() when using other providers, but I'd still be wary with recommending Migrate(). People should be informed of the downsides that still exist.

sander1095 avatar Feb 25 '25 11:02 sander1095

If Migrate() fails and the user isn't using a zero-downtime deployment strategy, you end up with an application that's fully down or unreliable.

For providers which implement migration locking properly, a migration failure should leave the database in a fully consistent state. Now, it's true that at this point your application instance has failed to start, but that can happen as a result of various other non-database startup failures; and just like users are expected to test applications in some sort of preproduction/test environment before pushing live, they're expected to test any new migrations as part of that, so the failure shouldn't in principle make it to production).

We generally do agree in the team that it's better/safer to apply migrations as part of deployment and not startup, but experience has shown that many/most users simply do not want that overhead (and may not have extremely high up-time requirements), and prefer to use Migrate().

roji avatar Feb 26 '25 09:02 roji