DbContext.Database.Mirgate() .. what about rollback? - entity-framework

So there is a extension function
Migrate()
dbContext.Database.Migrate();
which will apply all pending migrations to the database.
but if one of them fail . how do I roll back last step or last two migrations ?
say I have to apply A,B,C but roll back only B and C
is this even possible with code?

If you want to rollback B and C, simly specify target migration, i.e. A:
var migrator = new DbMigrator(new Configuration());
migrator.Update("A");
It is like: Update-Database -TargetMigration A

Related

Dis-Advantages of using EF 6.x.x Code First without Migration

I am fed up of using/running Add-Migration and Update-Database because lot of time we forget to run migrations on production database. So, we decided to delete all migrations from database table as well all migration classes. So, what if my __MigrationHistory table remains always empty and no migration classes. What is the main disadvantage?
No this is a bad idea, the [__MigrationHistory] is used to compare your current used conceptual model with the storage model.
1) Case: DbMigrationsConfiguration automatic:
[__MigrationHistory] keeps track for the last migration.
this.AutomaticMigrationsEnabled = true;
this.AutomaticMigrationDataLossAllowed = true;
as shown in the image above, the migrationId is the migration identifier and the model column is a base64 representation of the binary stream of your current conceptual model.
2) Case: DbMigrationsConfiguration non-automatic:
[__MigrationHistory] keeps track of every migration.
this.AutomaticMigrationsEnabled = false;
this.AutomaticMigrationDataLossAllowed = false;
Each migration level obtain a migrationId identifier which is used for migration level up/level/down.
Best practice: If you want to use the automatic migration just regenerate the migration and shipped to the custmer.
If you are using non-automatic migration.
1) If the customer need the data then just tranform the data with SQL to the new db schema
2) If the customer does not need the data then just drop the database an create it again with initialCreate.
If you want to create the database without any migrationHistory info:
// Create the database. You can generate it from SMO "Script database as" and if the database exist then just ignore the creation
// Do not forget to remove the [__MigrationHistory] rows.
DbContext.Database.ExecuteSqlCommand("SQLCreateDbScript.sql");
Database.SetInitializer<MyDbContext>(null);
using (var dbContext = new MyDbContext())
{
// Create DbContext and it works!
dbContext.Users.Add(new User());
dbContext.SaveChanges();
}
I hope this will help you to solve the problem!
And if you want something really with less Db-Schema then use NoSql with EF.
In Core version still not done but with the old version EF6 it is possible todo that (NoSql Db) with: http://www.brightstardb.com or use the Polyglot appoarch from microsoft https://msdn.microsoft.com/en-us/library/dn271399.aspx

EF code first - Model compatibility cannot be checked because the database does not contain model metadata

I have enabled automatic migrations. Then, I deleted my whole db. Next, i executed Update-database from command console, and it recreated my db. Then, I started my application only to see this error:
Model compatibility cannot be checked because the database does not
contain model metadata. Model compatibility can only be checked for
databases created using Code First or Code First Migrations.
So what exactly is that metadata, and how can I point entity framework to it?
PS. My database contains table named MigrationsHistory.
Here is a detailed description of the possible ways to resolve this which I wrote a while ago...
(not exactly what you're experiencing, hence not a duplicate per se, but with different scenarios in mind)
https://stackoverflow.com/a/10255051/417747
To summarize...
What works for me is to use Update-Database -Script
That creates a script with a 'migration difference', which you can
manually apply as an SQL script on the target server database (and you
should get the right migration table rows inserted etc.).
If that still doesn't work - you can still do two things...
a) remove the migration table (target - under system tables) - as per
http://blogs.msdn.com/b/adonet/archive/2012/02/09/ef-4-3-automatic-migrations-walkthrough.aspx
comments in there - that should fail back to previous behavior and if
you're certain that your Db-s are the same - it's just going to 'trust
you',
b) as a last resort I used - make a Update-Database -Script of the
full schema (e.g. by initializing an empty db which should force a
'full script'), find the INSERT INTO [__MigrationHistory] records,
just run those, insert them into the database, and make sure that your
databases - and code match,
that should make things run in sync again.
if it helps
Detach your local Database say example 'database1.mdf' from visual studio 'server explorer' and then open SQL server management studio right click on Databases > Attach and then browse the same 'database1.mdf' file .If you doesn't have access then copy&past both the mdf and ldf files into c drive and do attach.
Then open new query window on sql server then do copy your identity tables as like below query.
*'select * into [__MigrationHistory] from Database1.dbo.__MigrationHistory '*
Add this to your context:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
}
I use Entity Framework 6 , SQL 2008 R2 , VS 2013.
To solve this problem only use the following procedure :
1) delete existing db ( existing database that created with EF model{code first})
2) Run APP again.
Fore example query code (in Layout):
this code create db if my model is change and search username in user table.
<body>
#{
// Delete && Create ...
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<DBContext>());
var db = new DBContext();
var SearchingUser = db.Users.Where(c => c.UserName == "qwertyui");
if (SearchingUser.Count() == 0) {
var User = new Users { UserName = "qwertyui",Password = "12345678" };
db.Users.Add(User);
db.SaveChanges();
}
}
#RenderSection("scripts", required: false)
#RenderBody()
</body>
Package Manager Console > Enable-Migrations -EnableAutomaticMigrations
Configure Migrations/Configuration.cs
Package Manager Console > Update-Database

EF Code First: Migrating Database Initialized on Different Code Versions

I am using Entity Framework 5 RC, code first. I am struggling with migrating databases that were created on different versions of code. For example, Database A was created when table FooBar didn't exist. Database B was created after table FooBar was added to my model.
I have a migration written that adds the FooBar table. Is it my responsibility to check in the FooBar migration that the table doesn't exist before calling CreateTable? It seems that is the case since Database B doesn't have an entry for the FooBar migration and will attempt to run it.
At first the MigrationHistory table seemed like it would save me from adding these checks but since new databases won't have entries for migrations added before the database was created, I still need to do the checks myself. Is that the right way to go about it or am I missing something?
To get around an issue I had with adding Stored Procedures, I wrote a TSQL script to create a new table "_PreviousMigrationHistory" - which receives new entries from the "_MigrationHistory" table after my stored procedure scripts have run...
I did add a new column to both tables ( "VersionId", of INT - IDENTITY(1,1) ) which is what I use for comparison within my code.
This way you have the un-updated migration patterns available to you (__PreviousMigrationHistory), even after Code First Migrations have occurred.
Would this help?
**EDIT - sorry, I miss read the question. - Although I would think that new instances of the database would still go through the migration steps, which in turn should add the entries to the __MigrationHistory table?

What is the behaviour of JDO/ORMs when doing a persist() on an object?

Here's my scenario (I'm using datanucleus, JDO, but I think it applies to JPA also):
tx.begin();
Dog d = new Dog();
persistenceManager.persist(d);
d.setName("Doggie");
tx.commit();
In the above code, the name "Doggie" is not persistent in the database.
However, when doing
tx.begin();
Dog d = new Dog();
d.setSize(10);
persistenceManager.persist(d);
Dog d2 = dogDao.getDogBySize(10);
d2.setName("Doggie");
tx.commit();
it works!
Is this behaviour due to the fact that my "second" dog is somehow a managed instance, being taken out of the database, while in the first example, the object is unmanaged?
Is it a behaviour JDO-specific?
Thanks!
In the above code indeed the update to the name is present in the datastore ... when I run it. And indeed when you look at the log you see a very clear INSERT for the persist and then an UPDATE, unless using optimistic txns when you get a single INSERT with the latest value of name.

Entity Framework 4.1 Insert, Update Delete ASP.NET MVC3

I have a wizard where I am in updatemode. During this mode, I can actually insert, delete or update various records in the model. I am passing by reference to m CRUD methods. eg. MyMethod(ref Project project)
I was able to update by attaching my project to the context but when I also need to Delete during the same tranaction, update and delete do not do anything, How am I supposed to handle delete?
I do the following which does not work.
var FoundProjectUser = (from m in UserRoles where m.UserProfileId == member.UserProfileId select m);
if (FoundProjectUser.Count() == 0)
{
project.ProjectTeams.Remove(member);
}
ANSWER FOUND:
I found the problem. The problem is that in edit mode, the project is not attached to the context. I need to delete from the DBContext and not the project. Like this.Context.ProjectTeams.Remove(member);
.Remove will only flag the row for removal. You have to do entity.SaveChanges() to persist the changes.