I am using EF code first to create my database, the application is in production and test now so I need to run migrations to update the database as my model changes.
I have set up migrations based on the standard instructions and it works fine, against dev database one. I also have a second database that I want to bring in line with the current code base but this second database is in an unknown state.
What I want to know is can I generate a migration class against a different database and how do I do that? I can't seem to generate a migration class against anything other than the original database I specified when I set up migrations. I have changed the DB name in the app.config but it still looks at the original database when doing migrations.
How can I explicitly specify which database to generate the migration script against?
Migrations don't look at the database other than to check if a migration has been applied (__MigrationHistory). When you setup migrations it takes a snapshot of the code models and uses that when moving forward. So if you want to bring a database in an unknown state under migration control you will need to get it to match the code model.
You could do something similar to this: Create an idempotent script from your current database (update-database -Script –SourceMigration $InitialDatabase). This will be the equivalent of all migrations needed to create and bring your database current. Since you have an existing database where some of these objects exist, you will need to manually adjust the script by removing the code for items that already exist. Once you get it to apply, you should have a database that matches your model with a populated __MigrationHistory table.
Another option is to use a schema compare utility to make the databases match and then just copy the __MigrationHistory table over.
See Migrations Under the Hood.
Related
The question is only about EF Core 6 or above.
Let's say that I have two migrations in my project, call them InitialMigration and SecondMigration. The model snapshot contains information about the state of the database after both InitialMigration and SecondMigration were applied.
How can I determine the state of the database (model snapshot ???) if only InitialMigration were applied?
One may wonder why do I need that? Here is why. Once in a while we perform so called "squash" migrations. A squash migration means that all migrations and model snapshot are deleted and a new initial migration and a model snapshot are generated based on the current state of all C# classes in a model.
Since a squash migration can be created at some moment in time within a development cycle (say, a week or a month) and there are multiple environments involved (e.g., development, production), this opens a possibility that some extra migration could've been applied and / or created in one of the environments before or after the squash migration.
If there is a migration before a squash migration and it has not been applied to the database yet, then it is easy to detect, because the model snapshot does not match the database and that can be easily checked by iterating over all tables and all columns.
However, if there is a migration after a squash migration, then current model snapshot reflects the changes made in that second migration (SecondMigration) whereas the model snapshot if only InitialMigration were applied matches the database. Subsequently, I need to compare the database with the model snapshot as if only InitialMigration were applied. If they match then, I do not have scenario #1 described above and it is safe to proceed with the squash migration and subsequent migration(s) and if they don't, then I have a migration before squash migration and which was not applied to the database.
The "ugly" way that I have in mind is as follows:
Drop if exists / create another database, call it MyDatabaseSnapshot, by running (via C# code) Update-Database -m:Initial. That will create a database with only Initial migration applied. The name of the initial migration is always the same, regardless how many times we re-generate squash migrations.
Then I can compare my database, call it MyDatabase, with MyDatabaseSnapshot using SQL. The SQL is straightforward but tedious. In any case, I already have it.
I wonder if it is possible to perform the same without creating that extra database. I'd appreciate any ideas.
I am working on a project which is using Entity Framework code first for its data structure. It was created with code first, but was never migrated again and only has its initial migration data stored. Since then, the database has been modified directly through server explorer in VS2015.
There is no migration information about any changes and the database has critical information which I cannot lose.
Which brings me to my Questions.
If I create a new migration and update the database from it, will it wipe all changes which were not recorded in migrations and still leave the changes which were made as well?
The details of your question is a bit sketchy, but I will make some assumptions in order to help you along. Please correct where I am wrong.
I assume that you want to keep the data which resulted from the changes which were effected directly to the database, but you do not want to keep the changes that was effected to the database - in other words: keep the data but not the datastructures.
My advice is as follows
Always perform a full backup of your database when you are about to do something you are uncertain about.
If you can identify the tables you want to update, you can always use the SELECT INTO statement to create a quick backup of the specific tables only. These tables will not be removed when you do a EF database migration unless you explicitly script the deletion.
You can build the SELECT INTO statement into your EF migration via the Sql() method, or you can manually run the command against the database.
More information:
Click here to learn about EF code first migrations in general
Click here for a comprehensive code first migration reference
I believe following two posts will help you.
EF 4.3 Migration Walkthrough : http://blogs.msdn.com/b/adonet/archive/2012/02/09/ef-4-3-code-based-migrations-walkthrough.aspx
update:
Code First Migrations with an existing database
https://msdn.microsoft.com/en-us/data/dn579398.aspx
We are using Entity Framework code first migration technique for a while now. Everything works good however our Migrations folder has been growing big with numerous migration files because of changes we are making on entity schema. I was curious, is there a way we can update just one or specific number of files whenever there is change in entity so that our Migrations folder would look less messy. Also, i don't want to drop the table and recreate it since i will be loosing all the saved data.
You could simply merge all of your migrations into a new file (if you aren't concerned with keeping every migration).
To do so, simply delete every migration currently in the folder, and rerun the enable-migrations command and then the add-migration command like so.
Enable-Migrations
add-migration InitialCreate
You can try to use database initializer called MigrateDatabaseToLatestVersion. That automatically updates the database schema, when your model changes without losing any existing data or other database objects.
Database.SetInitializer(
new MigrateDatabaseToLatestVersion<YourDbContext,
DataLayer.Migrations.Configuration>());
I'm using EF 6.0.0 and .Net 4.5.
I face a very confusing problem. Me and one of my colleagues are working on the domain model section of our project on two different clients. The problem is:
1- Me and my colleagues start with the absolutely identical project and we are completely synced with the source control.
2- When I change the model for example add a property then Add-Migration FromA then Update-Database it works great. The generated code file contains just one command that is to add the column.
3- Meanwhile, after the db is updated and just before I check in something to source control, my colleague adds another property and then Add-Migration FromA then Update-Database. And guess what? This generated code file has a command to drop the column I newly added!!!
I added another column using native Sql, and fortunately the column is not going to be deleted.
I deleted the __MigrationHistory table and the remove column didn't get generated.
I turned off initializer Database.SetInitializer<MyContext>(null), no success.
So, my guess is that EF Migrations compares current model with the last one stored in __MigrationHistory table not the last local snapshot stored in .resx file. Am I right? Any way to solve the problem?
In our software, we have a customer base with existing databases. The databases are currently accessed via EntitySpaces, but we'd like to switch to EntityFramework (v6), as EntitySpaces is no longer supported. We'd also like to make use of the migrations feature. Automatic migrations are disabled, since we only want to allow database migration to an admin user.
We generated the EF model from an existing database. It all works pretty well, but the real problem we have, is, programmatically distinguishing between existing databases that match the model but have not yet been converted to EF (missing MigrationsHistory table), and empty/new databases. Converting existing databases works well with an empty migration, but for new databases we also need a migration containing the full model. Having an initial migration in the migration chain always clashes with existing databases. Of course we could create a workaround with external SQL scripts or ADO commands, creating and populating the MigrationsHistory table. But that is something we'd like to avoid, because some of our clients use MsSql databases, some use Oracle. So we'd really like to keep the abstraction layer provided by EF.
Is there a way to get EF to handle both existing, and new databases through code-based migrations, without falling back to non-EF workarounds?
My original suggestion was to trap the exception raised by CreateTable, but it turns out this is executed in a different place so this cannot be trapped within the exception.
The simplest method of proceeding will be to use the Seed method to create your initial database if it is not present. To do this...
Starting from a blank database, add an Initial Create migration and grab the generated SQL
Add-Migration InitialCreate
Update-Database -Script
Save this script. You could add it to a resource, static file or even leave it inline in your code if you really want, it's up to you.
Delete all of the code from the InitialCreate migration (leaving it with a blank Up() and Down() function). This will allow your empty migration to be run, causing the MigrationHistory table to be generated.
In your Migration configuration class, you can query and execute SQL dynamically using context.Database.SqlQuery and context.Database.ExecuteSqlCommand. Test for the existence of your main tables, and if it's not present, execute the script generated above.
This isn't very neat, but it's simple to implement. Test it well, as the Seed method runs after EVERY migration runs, not just the initial one. This is why you need to test for the existence of a main table before you do anything.
The more complicated approach would be to write a "CreateTableIfNotExists" method for migrations, but this will involve use of Reflection to call internal methods in the DbMigration class.