I have an IdentityServer that uses EntityFramework Core.
I use the code-first approach. Every time i want to edit the database, such as adding tables or adding more columns to any existing table, I just perform those changes in code and then in package manager console I use the commands to create the migration files.
When i run the IdentityServer, it has the following piece of code that performs the migrations.
GlobalConfig.DatabaseConnectionString = configuration.GetValue<string>("DatabaseConnectionString");
var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>().UseSqlServer(GlobalConfig.DatabaseConnectionString);
using (var context = new ApplicationDbContext(optionsBuilder.Options))
{
context.Database.Migrate();
}
'ApplicationDbContext' is just the class that extends IdentityDbContext and implements IApplicationDbContext.
Back to the main point, the
context.Database.Migrate();
applies the new migrations if I create a new database, and even with an existing database it applies the new changes.
Now is where the problem occurs. If I delete the columns or tables just added after the migration, if I run the program again, it will not perform the changes again. And why is this a problem?
I run the migration in my localmachine an it performs the migrations and updates the databases, but when someone pulls (in my particular case, my company's QA) my solution and runs the program, it does not perform that migrations on their machines.
I would like to know what am I doing wrong, or if that is something normal in EntityFramework.
I would like that the EF could check the database first and if it is not equal as specified in code, apply the changes... or something similar.
Thanks in advance!
Related
I'm working on an application with asp.net mvc that supports install, remove plugins.
When I want to install a new plugin I have an Install method that registers new routes and ...
For database, I use a code-first approach for creating database and every plugin has it's own context class.
My question is: when I want to install a new plugin, I need to create additional tables in my existing database, or create a new database if the database does not yet exist. And if those tables are already there, nothing should be created.
How do I achieve this?
Thanks in advance
Code First Migrations has two primary commands that you are going to become familiar with
Add-Migration will scaffold the next migration based on changes you
have made to your model since the last migration was created
Update-Database will apply any pending migrations to the database
When you develop a new application, your data model changes frequently, and each time the model changes, it gets out of sync with the database. You have configured the Entity Framework to automatically drop and re-create the database each time you change the data model. When you add, remove, or change entity classes or change your DbContext class, the next time you run the application it automatically deletes your existing database, creates a new one that matches the model, and seeds it with test data.
This method of keeping the database in sync with the data model works well until you deploy the application to production. When the application is running in production it is usually storing data that you want to keep, and you don't want to lose everything each time you make a change such as adding a new column. The Code First Migrations feature solves this problem by enabling Code First to update the database schema instead of dropping and re-creating the database.
I recommend to have look following link which makes you more clear about your problem.
https://msdn.microsoft.com/en-us/data/jj591621
I have a solution where I do not have one default database. I have a master Database that are returning a connection string for the customer that is requesting data, and each customer has their own database. I am using migration (and has AutomaticMigrationsEnabled set to false) and code first.
The command “update-database” is “excecuted” from the code (Database.SetInitializer(new MigrateDatabaseToLatestVersion());).
The first time is it all working fine, but when I afterwards will add a migration, I cannot, because there are pending migrations. I can not run update-database from VS because the connections string is set on runtime.
What is the right way to handle a setup like mine, with migrations and Entity Framework 6?
Thanks very much in advance
What you have is so called multitenant application. And yes, EF migrations can support such scenario, too.
You just have to change your migrator from the MigrateDatabaseToLatestVersion to a custom one that migrates the exact database the context is created for.
Then, forget about executing update-database from a powershell console. This always updates the default database! Instead, your custom migrator will automatically update the database you connect to.
Complete source code of the custom migrator can be found in my blog entry:
http://www.wiktorzychla.com/2013/05/entity-framework-5-code-first-multi.html
Be aware that due to a bug in eariler versions of EF, migrations in a multitenant scenario work correctly starting from EF 6.1.3.
Because of this bug, your multitenant application could incorrectly assign connection strings to newly created db contexts.
https://entityframework.codeplex.com/SourceControl/changeset/4187b1c308316a22b38ef533b1409024bc0f7406
Add-Migration and Update-Database from the console still refer to a database.
To create a DbContext, these commands either use its parameterless constructor (if you have one), or it instantiates an IDbContextFactory<T> if one exists and calls its Create method to get one.
The fact you don't use this specific database at run-time isn't really important, but you do need one somewhere at design time to allow you to add migrations.
I have an application using a EF model for the database. This application is going to run on multiple computers in the same network using one database. To make sure this works ok when there are updates. I want to control the migration and installation of the database.
I thought I could disable the EF initializer and in my application startup checks using context.database.Exists() and context.database.CompatibleWithModel if the application matches the database. If this is not the case I want to create it after I check if all client are offline.
But my problem is when I run context.database.create() ,
I get an error
{"Unable to update database to match the current model because there
are pending changes and automatic migration is disabled. Either write
the pending model changes to a code-based migration or enable
automatic migration. Set
DbMigrationsConfiguration.AutomaticMigrationsEnabled to true to enable
automatic migration."}
What is the best approach to controlling the creation of the DB and migrates from code? And not from the initializer.
The problem you've got seems not related to db creation. Your model just simply does not comply any more with what migrations states. Just run add-migration script to regenerate migration files and everything should work fine. If you would like to allow automatic migrations (not required to regenerate migration classes after model changes - but generaly this is a bad idea) just set AutomaticMigrationsEnabled = true in Configuration class for migrations and this will as well fix your error. To control migrations from code the best thing you could use is DbMigrator. You use it like that:
var migrator = new DbMigrator(new MyMigrationsConfiguration());
migrator.Update();
With the Update method you can define to which migration you want to migrate your db.
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.
All right, I'm using EntityFramework migrations, and they work fine, but when I run my application, (Web API) and the first time the context is used, the schema is created automatically for me. I DO NOT want that. I'd like to see an exception specifying that the tables do not exist or something like that.
In my configuration class I have something like this:
this.AutomaticMigrationsEnabled = false;
I thought that was going to be enough but EntityFramework keeps re-creating my database schema.
Since I'm using a Continuous Integration and Continuous Delivery process I want to use EF migrations to create the scripts for me and just check in my scripts and the scripts will be executed against the database for me (I already created that process)
So how can stop EntityFramework migrations for trying to create my database schema automatically when the application runs (when the context is accessed the first time in the AppDomain)?
Unset the database initializer for your context.
Database.SetInitializer<MyContext>(null);