Pages

Monday, March 26, 2012

Why Invalid Object Name 'dbo.__MigrationHistory'?


Unfortunately I am using  Entity Framework in my project. After migration support added to Entity Framework I thought using this feature may help me feel a little better about  Entity Framework . But the way migration is implemented in EF shows that nothing has changed. Migration has lots of problems and bugs.
After carefully doing all the required cumbersome procedures  Entity Framework migration failed to work and I found no workaround until I strangely faced the exception 'Invalid Object Name 'dbo.__MigrationHistory''. This exception give me  a clue about the cause of my problems.
It seems that Entity Framework team do not use appropriate testing methods and they only care about the main courses and are very negligent about alternative cases. For example in this case they presumed that always the default schema is dbo. It creates __MigrationHistory on the default schema, but queries for it on the dbo schema.
After a while I find another problem. Entity Framework also tries to insert rows into __MigrationHistory without specifying schema name.

Ok, I wrote this code to make Entity Framework script generator apply 'dbo.' before the __MigrationHistory. I know this is naive solution but at least it works.


// This is for scenarios in which your default schema name is not dbo and hence Entity Framework migration is not working properly.
// WARNING : Please be advised that this is a naive solution which its purpose is to just show how it could be corrected. You may not use this code without understanding and resolving any potential problem.
// For more information go to http://samondotnet.blogspot.com.au/2012/03/why-invalid-object-name.html
namespace ES.DataAccess.Migrations
{
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Model;
using System.Data.Entity.Migrations.Sql;
using System.Linq;
internal sealed class Configuration : DbMigrationsConfiguration<ES.Domain.ExaminationDbContext>
{
public Configuration()
{
SetSqlGenerator("System.Data.SqlClient", new SamSqlGenerator());
AutomaticMigrationsEnabled = false;
}
}
public class SamSqlGenerator : SqlServerMigrationSqlGenerator
{
protected override void Generate(System.Data.Entity.Migrations.Model.CreateTableOperation createTableOperation)
{
if (createTableOperation.Name.Contains("__MigrationHistory") && !createTableOperation.Name.StartsWith("dbo."))
{
var newCreateTableOperation = new CreateTableOperation("dbo." + createTableOperation.Name);
createTableOperation.Columns.ToList().ForEach(newCreateTableOperation.Columns.Add);
base.Generate(newCreateTableOperation);
}
else
base.Generate(createTableOperation);
}
protected override void GenerateMakeSystemTable(System.Data.Entity.Migrations.Model.CreateTableOperation createTableOperation)
{
}
protected override void Generate(System.Data.Entity.Migrations.Model.InsertHistoryOperation insertHistoryOperation)
{
if (!insertHistoryOperation.Table.StartsWith("dbo."))
insertHistoryOperation = new InsertHistoryOperation("dbo." + insertHistoryOperation.Table, insertHistoryOperation.MigrationId, insertHistoryOperation.Model, null);
base.Generate(insertHistoryOperation);
}
}
}
view raw gistfile1.cs hosted with ❤ by GitHub

1 comment:

  1. The same problem was present when MS introduced membership API for ASP.NET for the 1st time. They only know and support "dbo"'s!

    ReplyDelete