EF Code First Database migration error on second start - entity-framework-4

I have a web application with local database in production environment. In new build I decided to change database and added database migration.
I ran Enable-Migrations in NuGet console.
Program has generated 201410141412423_InitialCreate.cs file as I already had database - there're some code that initialize my database schema.
Then I added one field in model Workstation
public class Workstation
{
public int Id { get; set; }
[StringLength(15)]
public string Name { get; set; }
public DateTime LastCall { get; set; } //this field was added
public string UserConfiguration { get; set; }
private readonly ICollection<StatusBase> _statuses = new Collection<StatusBase>();
public virtual ICollection<StatusBase> Statuses
{
get { return _statuses; }
}
}
I ran Add-Migration WorkstationLastCallAdded command in NuGet console. New file with migration logic was generated with next code:
public partial class WorkstationLastCallAdded : DbMigration
{
public override void Up()
{
AddColumn("dbo.Workstations", "LastCall", c => c.DateTime(nullable: false));
}
public override void Down()
{
DropColumn("dbo.Workstations", "LastCall");
}
}
I also added next code in Global.asax file to update my database
protected void Application_Start()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<AppDbContext, MigrationConfiguration>());
}
Then I build it and run, and everything works fine.
When I deploy new build to server, there's a database file with some data on the server. The database has old scheme - without LastCall field. So I expect migration updates my database and I won't loose any data.
When I run my site after deploy - everything works fine. Data is not lost and database is updated correctly.
If I restart server or IIS and run my site again - I've got 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.
When I open local db and watch _MigrationHistory table - there're two rows with 1410151540264_InitialCreate and 201410141956597_WorkstationLastCallAdded migration id's.
Could anybody help me please? Any ideas what's going wrong? Why it works correctly on first run after update but fails on the second?
Thank you in advance.

IIRC, the answer it pretty simple. You have two migrations:
201410151540264_InitialCreate
201410141956597_WorkstationLastCallAdded
You InitialCreate miration is newer than WorkstationLastCallAdded migration. Why? Because InitialCreate is implicitly added to _MigrationHistory table when your DB is created for the first time and you have no migrations. The timestamp for InitialCreate in this case is, of course, equal to current server time. WorkstationLastCallAdded, on the other hand, has a fixed timestamp which reflects the time when you ran Add-Migration WorkstationLastCallAdded command. Therefore, if you create a database after you've created WorkstationLastCallAdded, InitialCreate will be the 'newest' migration.
What happens next? Db initializer searches for the newest migration and finds InitialCreate. Then it compares InitialCreate model hash with current model hash and sees that these hashes are different (of course they are, you have changed your model!). And then you got your error.
The easiest way to solve this is to rename your WorkstationLastCallAdded timestamp (in migration designer file) to something like this:
99999999999999_0001_WorkstationLastCallAdded
A bunch of nines ensures that this migration is older than InitialCreate. 0001 reflects the order of migration. If you want to create another migration, you should name it like this:
99999999999999_0002_SomeOtherFieldAdded
Hope this helps!

Related

Migration with Entity Framework 6 code first

I have an ASP.NET MVC project using EF code first and migrations.
I am trying to add a new property to a class. For that I create the migration code in order to add the specific column in the table related to that class.
My migration code is the following:
public partial class Add_DataRequisicao_to_BiblRequisicao : DbMigration
{
public override void Up()
{
AddColumn("dbo.BiblRequisicoes", "DataRequisicao", c => c.String(nullable: false, defaultValue: "01/01/1900 00:00"));
}
public override void Down()
{
DropColumn("dbo.BiblRequisicoes", "DataRequisicao");
}
}
And the property to add to the class is the following:
[Required]
[Display(Name = "Data Requisição")]
public string DataRequisicao { get; set; }
When I publish the project and go to the project web site, I get the following error message:
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.
Inspecting the database, I see that the migration was run with success because the column was created. In the migration table, there also is a new entry that indicates that the migration ran.
The migration entry:
MigrationId: 201704261436437_Add_DataRequisicao_to_BiblRequisicao
ContextKey: WebAppInvestigacaoMultimedia.Migrations.Configuration
Model: 0x1F8B0800000...
ProductVersion: 6.1.3-40302
I don't understand why I get the error message if the migration ran with success and the name and the type of the property is the same as the add column of the table.
This error is usually linked to changes to the model that haven't been added to a migration script yet.
If you look at the folder where you have your migrations, you should have resx files, those files contain a "snapshot" of the model at the time the migration was generated. It therefore knows if there are changes that have been made to the model and will not let you do an Update-Database if there are pending changes.
To resolve the issue, you either have to rollback any changes you made to the model since the last migration you made, or create a new migration using Add-Migration and then do Update-Database.
If you're working with a team, those issues happen sometimes if both you and others have made changes to the model or created migrations. Check this interesting MSDN article to get a few insights on how leverage those issues.

Can't update Database with EF Code-First

I am using EF code-first migrations. I added a new property to my model but it doesn't reflect as a column in the database.
Configuration.cs
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
Global.asax.cs
Database.SetInitializer(new MigrateDatabaseToLatestVersion<DbContext, DbMigrationsConfiguration<DbContext>>());
using (var context = new MyDbContext())
{
context.Database.Initialize(true);
}
I have already tried the update-database. It says no pending migrations.
EDIT:
My EF is a separate Class Library Project.
There's another Class Library Project that stores all the Models.
And the Main (Startup) Project is an MVC Project.
Where should I include Migrations?
Also, Add-Migrations Initial always gives me EMPTY Up() and Down() methods.
this worked for me first of all take backup of your database then delete migrations folder in project and delete __MigrationHistory table in database
then run this command
Enable-Migrations -EnableAutomaticMigrations -Force
then add migration
Add-Migration InitialMigration
and finally update database with
Update-Database
Verbose can fix this problem. In your package manager console run
Update-Database –Verbose
Before executing "Update-Database" command did you run "Add-Migrations"?
The Add-Migrations command will generate the necessary migration script to update the database.
Also, do you have a _MigrationsHistory table in your database?
Could you update your code to point to your MyDbContext rather than the base DbContext? And I believe DbMigrationsConfiguration<DbContext>>() should also point to your dbcontext type.
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyDbContext, DbMigrationsConfiguration<MyDbContext>>())
*Add Your New Model Frst: User Model -id,fname,lname,adress,ect...
*Define in your Application db context the new model as a new set Example :
public DbSet Users{ get; set; }
*Create Migration : add-Migration YourMigrationName
*Update Database

EF not seeding database on creation

I am using Entity Framework to create and seed my database using Code First and the MigrateDatabaseToLatestVersion initializer. The issue I am having is when I launch the ASP.NET MVC app without a database create EF will create the database but will not seed on the first run through. If I kill iisexpress and relaunch the app after creating the database my seeds go in fine. I would expect my seeds to be ran after the database gets created but I don't even hit a break point in my seeds method on the first run through. I hit break points on the second run through without problems but it is annoying to have to run the app twice after killing the DB just to get my seeds to work.
Below is my Configuration class:
public sealed class Configuration : DbMigrationsConfiguration<CompassDb>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
}
protected override void Seed(CompassDb context)
{
ModuleSeed.Seed(context);
PermissionGroupSeed.Seed(context);
var permissions = PermissionSeed.Seed(context);
var roles = RoleSeed.Seed(context, permissions);
UserSeed.Seed(context, roles, permissions);
OcmPluginSeed.Seed(context);
SCACSeed.Seed(context);
ModuleConfigurationSeed.Seed(context);
}
}
I am calling this in my Global.asax file.
Database.SetInitializer(new MigrateDatabaseToLatestVersion<CompassDb, Configuration>());
using (var db = new CompassDb())
{
db.Database.Initialize(true);
}
I did have a query to get a version number from the db on page load to create the database but calling the initializer directly seems a little cleaner. I was having the issue before when I was making a DB call through EF as well. I moved away from the DB call because I am only using EF for the automatic DB creating and migration then I switch to Dapper for any database communication.
I found this post here where people were having the same issue as me but it doesn't seem like it was ever resolved.
UPDATE
I found out that the issue is related to my migration files. I updated the primary keys of all my models from int to long and had to delete my current migration files. After deleting the files everything started working as normal, the database would be created and seeded on the same request. I then created my initial schema migration and am back at the same issue where the database does not seed until the 2nd time launching the site. I am using ELMAH in the project and have to update the first migration file to execute the sql file that is included when installing ELMAH via nuget. This could be related to the issue and I will do more testing to see if this is the cause.
I think I had the same or similar problem. Try to make a manual initializer. It's clean, simple and short. See this example:
Public Class CustomDbInit
Implements IDatabaseInitializer(Of MyContext)
Public Sub InitializeDatabase(context As MyContext) Implements System.Data.Entity.IDatabaseInitializer(Of MyContext).InitializeDatabase
If Not context.Database.Exists Then
context.Database.CreateIfNotExists()
' Some other processes, such as WebMatrix initialization if you're using SimpleMembership like I do
End If
End Sub
End Class
Then on the Global.asax Application_Start method, initialize it like this:
Dim context As New MyContext()
If Not context.Database.Exists Then
Database.SetInitializer(New CustomDbInit())
context.Database.Initialize(False)
End If

How to update database model on a deployed asp mvc web site without losing data

How to update database schema (model) in asp mvc website after it is deployed, without losing any previous data?
I have just deployed an MVC5 website to azure web site. Everything is fine, thus I started to uploading some data. Then I figured out something that I needed to update. It is simple, I just want to make a slight change in its database schema.
In local machine (development stage), we can just run
Update-Database
on package manager console. And here is the question? how to do the same idea to the published version? I have not tried to re publish my solution, fearing that the data will be lost (the data is plenty, too much to re upload).
I am using entity framework 6 code first with migration enabled:
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
All I want to do is just adding an attribute to one of the data row:
public class MyViewModel
{
public string Name {get;set; }
public string Content { get; set; }
}
to:
public class MyViewModel
{
public string Name {get;set; }
[AllowHtml] //ADDING THIS ONLY
public string Content { get; set; }
}
Thanks.
you can, among other solution, use this
Database.SetInitializer(new MigrateDatabaseToLatestVersion<BlogContext, Configuration>());
where BlogContext is your context and Configuration is the configuration class (the one descending from DbMigrationsConfiguration<T>) generated by code first.
Of course you have to republish your application (at least binary part).
Please also read http://msdn.microsoft.com/en-us/data/jj591621.aspx, specially the last paragraphs.
Welcome to the scariness that is Code First Migrations in a production environment! One thing to note, if you enable automatic migrations, you can never revert the migration. Instead, it's recommended that you don't do automatic migrations. Instead, from your console, run add-migration "migrationName". This will add a migration to your migrations folder with an up and a down method, where you can see all the changes that are related to that migration. You can see what sql will be run against the database by running update-database -script. The changes will not actually be run, but you can see what sql is generated. Here is a good walkthrough on Code First Migrations and deployment and all the changes that are necessary in the web.config file.
I believe that allowing data loss is turned off by default when you use automatic migrations.

EF6 "No migrations have been applied to the target database."

In an mvc5 application, I created a CodeFirst data model, and performed several migrations on it.
I then refactored my project, and moved all the data/migrations classes to a new project, which is referenced by my presentation tier.
The dbcontext successfully connects and performs read/write operations on the DB after the project change.
When I made a minor change to the model and ran add-migration, the EF created a migration with the code to create the database from the beginning, like it didn't "see" the existing tables.
Of course, when i ran
Get-Migrations -ConfigurationTypeName ConfigurationDbContext
i got
No migrations have been applied to the target database.
The __MigrationHistory in the DB is intact and the migrations/configuration classes namespaces didn't change. Also, apparently, the ConnectionString is OK, otherwise he would have trouble working with the db and i would get the "The model backing the context has changed since the database was created" or similar error.
EDIT:
As suggested in the comment, I specify the exact connection string in the DbContext constructor, and not the connectionstirng name in web.config, as it was in the original mvc project.
Still no history/changes in the db when running Get-Migrations and update-databse.
when I run Get-Migrations -ConfigurationTypeName My_Namespace.Migrations.ConfigurationDbContext.ConfigurationDbContext
I get
No migrations have been applied to the target database.
If I try to specify the connection string
Get-Migrations -ConfigurationTypeName My_Namespace.Migrations.ConfigurationDbContext.ConfigurationDbContext -ConnectionString "Server=my_server;Initial Catalog=my_catalog;User Id=my_user;Password=my_pass" -ConnectionProviderName="System.Data.SqlClient" -verbose -debug
the PM gets stuck on >> sign, until I restart or clear the window...
if I omit the ConnectionProviderName="System.Data.SqlClient", the console asks me to enter it, and after I enter, it shows connection to the correct db,
Target database is: 'my_catalog (DataSource: my_server Provider: System.Data.SqlClient, Origin: Explicit)
but still no migrations...
No migrations have been applied to the target database.
Why can it be and what can be done to further investigate/resolve this issue?
EDIT 2:
the constructor of my dbcontext is simple:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base(
"Server=my_server_name;Initial Catalog=my_db_name;UserId=my_username;Password=my_password"
)
{}
public DbSet<Model1> Model1Entities { get; set; }
public DbSet<Model2> Model2Entities { get; set; }
public DbSet<Model3> Model3Entities { get; set; }
}
it is based on IdentityDbContext as in the template mvc5 applicaiton, because I didn't want to create a different dbcontext for it.
and the ConfigurationDbContext is automatic
internal sealed class ConfigurationDbContext : DbMigrationsConfiguration<ApplicationDbContext>
{
public ConfigurationDbContext()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(ApplicationDbContext context)
{
}
}
Thanks!
Well, the answer is that somehow during the refactor the namespace of ConfigurationDbContext changed from
demo10.Migrations.ConfigurationDbContext
to
demo10.Migrations.ConfigurationDbContext.ConfigurationDbContext
and the ContextKey column of the __MigrationHistory table should be the ConfigurationDbContext namespace (you can omit the DbContext, like to have
demo10.Migrations.Configuration
in the table for
demo10.Migrations.ConfigurationDbContext
namespace).
Leaving an answer here as I had a similar problem that wasn't solved by this:
I had the password wrong in the app.config I was using against a different environment. Get-Migrations doesn't give you an error about failed credentials, it just tells you "No migrations have been applied to the target database", which is hugely misleading.
Hopefully someone else who comes across this will discover it's as simple as a typo in their connection string!
edit: the irony of typo-ing the word typo in an answer about my typo.
I've run into issues in development having the __MigrationHistory table open in SQL server Management Studio...
After closing the table (which was NOT open for edit, just select), somehow fixed everything.
Chiming in with an edge case of my own: check to see if your DB is in mixed mode or purely in Windows Auth mode.
Had a 2014 install go sideways such that sa was disabled and there was no Windows account authorized (client had a hosting upgrade to 2014, so I had to match it). I managed to stand it back up and regain Windows account access (real edge case voodoo shit), but didn’t realize it was stuck in Windows Auth mode only. Once I switched it back to mixed mode, I suddenly had a connection again. D’oh!
This happened to me just now and the issue was that my sa password had expired and needed to be reset. I was still logged in from a previous session so I could run queries no problem but when I disconnected and reconnected I had to reset my password! Took me an hour to figure that out though :/
I had this problem when i split the code into multiple projects. Solved by seting the default project of the solution to the one that have the correct connection string.
Get the hint by running the command:
get-migrations -Verbose
eflocation\ef6.exe migrations list --verbose --no-color --prefix-output --assembly dataproject \project.dll --project-dir dataproject\ --language C# --data-dir defaultproject\App_Data --root-namespace dataproject --config defaultproject\Web.config
The Web.config or app.config file that you see after running the command should be taked from the default project.
I had the same problem after I changed the name of my project. I had also recently rebooted the server.
So, I had to do two things to solve the problem:
Start the SQL Server service
Create an Update query for the
__MigrationHistory table to change the value of the ContextKey column from Old_ProjectName.Migrations.Configuration to New_ProjectName.Migrations.Configuration.
That sorted it for me.

Resources