Database Migration and Azure Mobile Service adventure

During the last months I have worked with an API backend for a mobile application. Azure Mobile Service with a .Net backend is our infrastructure platform.  There was a lot of struggling to get Entity Framework Database Migration work the way I wanted it to work. But the solution was quite easy, but needed some few changes that I think shouldn’t be needed at all.

By default when creating an Azure Mobile Service Backend with Entity Framework, the Automatic migration is turned on. In my case I don’t want the model and the tool take control over my database schema and migration, so I turned off that feature. It was now the adventure started ;)

How Entity Framework Database Migration handles database schema


By default Entity Framework uses “dbo” as the default database schema. So the user that logins to the database when a Migration should be applied need permissions to that schema. When creating an Azure Mobile Service a random SQL Server user will be created and added to the associated database. That user doesn’t have permissions to the “dbo” schema, but to another schema that is based on the name of the Azure Mobile Service name. If you create an Azure Mobile Service with the name “mymobile-test”, the SQL Server user will have permissions to a schema with the name “mymobile_test”. That means that you need to change the Entity Framework default schema to “mymobile_test”. This can be done by overriding your DbContext’s OnModelCreating method, and use the DbModelBuilder’s (an argument to the OnModelCreating method) HasDefaultSchema method:

 

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var schema = ServiceSettingsDictionary.GetSchemaName();

if (!string.IsNullOrEmpty(schema)
modelBuilder.HasDefaultSchema(schema);
}

 

The code above will be part of a DbContext created by the Azure Mobile Service project template in Visual Studio. The ServiceSettingsDictionary.GetSchemaName will take the value of the appSettings “MS_MobileSeriveName” and use it as the default schema.

Note: If you name your Azure Mobile Service project in Visual Studio to a different name than your Azure Mobile Service in Azure, your local code will use the project name as your mobile service name, but in Azure the name you gave the Azure Mobile Service. So when you add a migration with the “Add-Migration” command, the Entity Framework will use your local service name as the default schema. It will give you permission denied when you publish your code to Azure and run the migrations.

I named the Azure Mobile Service in Azure with the name “mymobile-test”, but in Visual Studio I call my project “My.Mobile”. When I added a migration it added the My.Mobile as a schema to the migration file and also set the DefaultSchema in the migration’s .resx file to “My.Mobile”. The migration worked fine on my dev machine, but when my code was published to the Azure, I got permission denied against the schema “My.Mobile”. I removed the schema from my migration files but left the DefaultSchema in my migration’s .resx file. Now things started to work better, BUT! Because the default schema set to the DbContext is different from the one in the .resx file, the migrations will fail because Entity Framework notice a different between the schemas, it want me to run “Add-Migration” again to get the new model changes. In this case a schema change. The reason why I can’t use the “mymobile-test” as the schema name in my migrations files, is because I have two environment, test and production, they uses different names and the SQL server user for those have permissions to its own schemas. So that gives me more problem when it comes to migrations. The main problem is the migrations .resx file and its DefaultSchema key. If Entity Framework will just ignore it everything should work great by just setting the DbModelBuilder’s default schema to the name of the Azure Mobile Service.

How did I fix the problems with database migrations?

 

I removed the code that will set the DbModelBuilder’s default schema to the Azure Mobile Service name from the DbContext OnMdelCreating method:


protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//var schema = ServiceSettingsDictionary.GetSchemaName();

//if (!string.IsNullOrEmpty(schema)
//modelBuilder.HasDefaultSchema(schema);
}

 
Now Entity Framework will use “dbo” as default. But the Azure Mobile Service user against the SQL Server doesn’t have permissions to the “dbo” schema, so I just gave the user permission to it.

GRANT CONTROL ON SCHEMA::[dbo] TO [The Generated User Login]

I did the same thing to the production SQL Server for my Azure Mobile Service too.  I can now add migrations without worry about permission problems and schemas based on the Azure Mobile Service name.

My next blog post will be about how to disable Automatic Migrations and take control over the migrations.

Please feel free to follow me on twitter if you want to know when I publish more blog posts. @fredrikn

4 Comments

  • Thanks! I've been more than a week with this issue. I was going crazy! Now my test backend has migrations enabled.

  • I get this error on MobileService: Boot strapping failed: executing 'WebApiConfig.Register' caused an exception: 'User does not have permission to perform this action.
    CREATE SCHEMA failed due to previous errors.'.

    And I try to grant permissions but I get an error from management studio saying that either the user doesn't exist or I don't have permissions.

    Cannot find the user 'IswFCYxVCSLogin_**************', because it does not exist or you do not have permission.

    Here's my query:

    GRANT CONTROL ON SCHEMA::[dbo] TO [IswFCYxVCSLogin_**************]

    I've tried to run the query on the master database and the database connected to my mobile service. I have two databases on the mobile service.


  • Hi,

    I am facing the same issue and trying to resolve it. However I am not much experienced with azure mobile service or general sql databases and I don't know what does it mean:
    =============
    so I just gave the user permission to it.
    GRANT CONTROL ON SCHEMA::[dbo] TO [The Generated User Login]
    =============

    Where I should run this command and where I can get [The Generated User Login] from?

    thank You very much in advance!
    Darek

  • You could hardcode a schema name. You could even hardcode the schema name equal to the name of your Mobile Service

    var schema = "NAME OF YOUR MOBILE SERVICE";//ServiceSettingsDictionary.GetSchemaName();
    if (!string.IsNullOrEmpty(schema)
    modelBuilder.HasDefaultSchema(schema);

    You could pass this string to Web.Config to a custom key other than "MS_MobileSeriveName" if you dont want to simply right a string there.

Add a Comment

As it will appear on the website

Not displayed

Your website