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

Migration source generator #34739

Closed
alrz opened this issue Sep 23, 2024 · 6 comments
Closed

Migration source generator #34739

alrz opened this issue Sep 23, 2024 · 6 comments

Comments

@alrz
Copy link
Member

alrz commented Sep 23, 2024

As an alternative to dotnet ef migrations add workflow, a source generator can monitor the context entities and generate a new migration if anything is diverged from the snapshot. A new update snapshot command preserves the generated file and updates the snapshot. This has the advantage of immediately seeing the changes and delaying the update until the change is final.

@AndriySvyryd
Copy link
Member

To build the model the source generator would need to run the code in OnModelCreating and load the output assemblies of the projects currently being worked on. This is not supported in general.

@AndriySvyryd AndriySvyryd closed this as not planned Won't fix, can't repro, duplicate, stale Sep 25, 2024
@alrz
Copy link
Member Author

alrz commented Sep 26, 2024

Of course the generator can interpret the content of that method, perhaps with aone limitations, it wouldn't be straightforward but I don't think this should be the reason to discard the idea altogether, especially if it could address #2174.

@AndriySvyryd
Copy link
Member

We tried it. It cannot be done in a non-hacky way. Instead, we'll be pursuing more actions triggered by build: see #24894 and #33103

@roji
Copy link
Member

roji commented Sep 26, 2024

Of course the generator can interpret the content of that method, perhaps with aone limitations [...]

In addition to @AndriySvyryd's answer above, consider that OnModelCreating can contain totally arbitrary code including control flow (e.g. loop over all entities and do some configuration on them); it can also call other methods. In addition, users can have additional model building in EntityTypeConfiguration etc.

The code in OnModelCreating is also very open and extensible, e.g. specific providers can add additional methods to configure provider-specific things in the model. We'd have to basically duplicate all the runtime model building logic as static compile-time interpretation of the same code by the source generator, including pluggability for providers.

Because all of the above, source generators simply don't work here.

In addition, generating a new migration any time a change is detected simply isn't the way migrations should work; people play around with model changes, and need to be able to explicitly determine when those changes are final and a migration is generated. Users also need to be able to determine which changes are bundled together into a logical unit - representing a single conceptual change - rather than having tons of very small changes, which don't mean anything.

Finally, the point of source generators is to have online, reactive source generation as the user is changing their code in the IDE; but there's no need for any of that with migrations - they're a purely "offline" thing that is only executed when you need to evolve your database. So there's really very little value in doing any of this, AFAICT.

@alrz
Copy link
Member Author

alrz commented Sep 26, 2024

@roji @AndriySvyryd

I agree that this is probably not the "mechanism" to enable this workflow, but I would like to discuss how it could be done without a generator.

In addition, generating a new migration any time a change is detected simply isn't the way migrations should work;

That's not what I was proposing, you get only one as long as you don't update the snapshot. Let's call this "pending migration" which always generates idempotent scripts and updates in-place.

You can choose to update the snapshot at any point and start a new migration if the changes are not compatible or you want custom before/after code to run for more involved scenarios or simply because you want to control the ordering.

Usually you add a bunch of migrations in a feature branch in smaller iterations but once merged to main you probably only want one for simple additive changes which is the most common for normal usage (see also #2174).

So I guess my question is how to do dotnet ef migrations add-or-update without updating the snapshot to maintain a single migration for the lifecycle of the feature branch and only deliberately update the snapshot to reset the checkpoint for future changes (this is analogous to public API analyzer which tracks published/unpublished changes).

@roji
Copy link
Member

roji commented Sep 27, 2024

That's not what I was proposing, you get only one as long as you don't update the snapshot.

I might be confused, but you may have an incorrect mental model of how migrations work in EF - users do not update the model snapshot, the model snapshot is automatically generated by EF (as part of generating a migration). All the user does is update their code model, and when they decide they want to generate a migration for a pack of changes, they generate a migration (dotnet ef migrations add). That's the only user gesture needed.

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

4 participants