0
votes

I have a DBContext object which contains the definitions of all my database objects. When I ran the application for the first time, it created the database. This is now in production.

I now have needed to make model changes in DEV and so will need to use Code First Migrations to generate a SQL script that makes the required schema changes in prod when I release.

As I understood it, I could add a new migration with the add-migration command and it would compare what is in my existing database with the model definition and generate a script for me that would allow me to update the database. However when I run the add-migration command, it generates a migration for me that is a full database create, not simply the new objects.

My database objects are in a separate class library, I have opened up package manager console, selected the default project to be my DB class library.

Under Configuration.cs I have

  internal sealed class Configuration : DbMigrationsConfiguration<Centrica.EMT.Database.Context.EmtDataContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
            ContextKey = "Centrica.EMT.Database.Context.EmtDataContext";
        }

And in the app.config of that class library I have

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <connectionStrings>
    <add name="Centrica.EMT.Database.Context.EMTDataContext" connectionString="Initial Catalog=EMTProd;Data Source=WYCVWWEBD016\COMPUTECLUSTER;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
  </connectionStrings>
</configuration>

yet it doesn't seem to find that database and generate an update script, it just creates a brand new full database creation script for me when I create a new migration.

Am I not able to create an update script? Did I have to have an existing migration performed initially as a baseline? Have I configured it wrong for how to find the existing database?

Updated

  public class EmtDataContext : DbContext
    {
        public EmtDataContext()
        {
            //todoSystem.Data.Entity.Database.SetInitializer(new CreateDatabaseIfNotExists<EmtDataContext>());
            var objectContextAdapter = this as IObjectContextAdapter;
            var objectContext = objectContextAdapter.ObjectContext;
            objectContext.CommandTimeout = Database.Connection.ConnectionTimeout;
        }
1
I think there is a slight misunderstanding here. When you first enable migration, the very first migration script is indeed full of table create. It is only after you modify something afterwards and run add-migrations, you will have another migration script that describes the delta. I have similar setup, and I have a file named <somedate>_InitialCreate.cs that is indeed full of CreateTable() - Aditya Santoso
Ah I see. I just ran the application and had the initialiser set to CreateDatabaseIfNotExists. Is there any way now I can use migrations given I didn't create an existing one? - NZJames
Yes. You can use MigrateDatabaseToLatestVersion, which is what you should be running in production anyway - Aditya Santoso

1 Answers

0
votes

Migrations do not look at the database to determine the script - they look at the last migration and do a diff. If there is no prior migration, you get the entire database scripted. The way around this is to do "add-migration Baseline -IgnoreChanges" which just updates the snapshot with no code generated. Then all subsequent migrations will be the new objects. The only thing EF looks at in the database is the __MigrationHistory table to see if the migration has been applied.

As I understand it, your DEV is now ahead of PROD so you have a couple of alternatives:

1) Establish a baseline before your model changes:

  • Identify your model changes and roll them back.
  • add-migration Baseline -IgnoreChanges // This will create a snapshot of current state.
  • update-database // Adds __MigrationHistory and inserts record.
  • Reapply your model changes, add-migration will now contain just the changes.

2) Do an add-migration which will script all objects. You can comment out the objects that already exist and apply the rest to PROD.

See https://msdn.microsoft.com/en-US/data/dn481501

As for production, you will get mixed opinions on whether you should run migrations against a PROD database. Our DBAs rejected that, so we simply give them generated scripts. See http://cpratt.co/migrating-production-database-with-entity-framework-code-first/#at_pco=smlwn-1.0&at_si=54ad5c7b61c48943&at_ab=per-12&at_pos=0&at_tot=1