My database model (sometimes referred to as "context") is dynamically assembled at startup based on which services and/or plugins are installed. Plugins and services export their model definition fragments through my IoC container and the application core picks them up and runs them when the DbContext.OnModelCreating
method is called.
The question is: Can I (and how do I) use Code First Migrations with this setup?
(below is more information on what I've tried and what particular problems are)
In my previous project, the database was inherited from some old code so we couldn't use any of the Code First database generation stuff anyway. We simply kept a long line of delta scripts and executed them manually on deploy (it was a single-host kind of project).
Now I'm starting a new project, and this time, the database is brand new, ready for Code First to play with. Initially, I was all excited about Code First Migrations, seemed like the way to go. Until I actually tried it. The initial attempt, quite obviously, failed due to the absence of an explicitly defined DbContext
in my project.
So far, it looks like the only viable option is to manually code migrations, with which I am perfectly fine. However, it turns out that this is not as simple as just creating a few classes inherited from DbMigration
.
After some experimentation on a small test project, I was able to find out that the migration autogenerator adds an implementation of IMigrationMetadata
, which, among other things, contains a hash of my model as the values of the Source
and Target
properties. Presumably, this hash is then used to identify a path across migrations from the "current" state of the database (as recorded in the __MigrationHistory
table) to the newest state as defined by the model in code. This totally makes sense, but...
Naturally, I have no idea where to get that hash for my model, which makes me unable to implement IMigrationMetadata
on my migrations.
On the other hand, I see that the metadata interface is not included in the DbMigration
class itself, which makes me think that it might be optional. It then follows that migrations can actually work without the hash values, but the question is - how?
All the information I could find on the internet is just simple, very basic tutorials. No information on how to create migrations manually (and whether it's even supported). No documentation on how it actually works and how to extend it. And it is not quite obvious from outside.
I am ready to resort to ILSpy at this point, but the whole EF is so complex that I fear I may not be able to find what I need in reasonable time.
Here are a few ideas that you could pull together to find a solution that works for you. I realize I mentioned some of these in our other thread, but I'm including them here for others reading this question.
When you run the project , an extra table is created in the database.
The hash is always created with the help of EdmMetadata Entity and the current code first model. It is SHA-256 hash stored in the EdmMetadata table of the database. You can get it from that table.
Methodology to be followed will be:
Get the hash of the current model using
Check whether the model in the code (new model) is compatible with the model in database(old model) using
This method returns bool.
If it is not compatible, then delete the existing tables in the database.
Create new tables
Save the current hash to the databse
Seed the data.
The code may look like:
Be sure to make the class inherited from