Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
sander1095 opened this issue Feb 20, 2025 · 4 comments
Assignees

Comments

@sander1095
Copy link
Contributor

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

@roji
Copy link
Member

roji commented Feb 20, 2025

/cc @AndriySvyryd

@AndriySvyryd
Copy link
Member

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.

@sander1095
Copy link
Contributor Author

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.

@roji
Copy link
Member

roji commented Feb 26, 2025

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().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants