Contents tagged with .Net

  • Azure Mobile Service and manual database migrations

    In my previous blog post I wrote about my experience with Azure Mobile Service and Database migrations. In this blog post I will explain step by step how to get manual migration in place.

    I like to have my migrations close to the domain model which I often create as a separate class library. Then I enable database migration for the Domain project using Package Manager in Visual Studio (VS) (Tools -> NuGet Package Manager -> Package Manager Control):

    Enable-Migrations

    By default Azure Mobile Services uses automatic migration with code first. It’s also configured to no support data loss during migrations so we need to turn this off (if you don’t care about data loss).

    When database migration is enabled a Configuration.cs file will be added to the Migrations folder. To add the following to its ctor (constructor) we will disable automatic migrations and data loss is allowed during a migration:

      public Configuration()
      {
    AutomaticMigrationsEnabled = false;
    AutomaticMigrationDataLossAllowed = true;
    MigrationsAssembly = this.GetType().Assembly;
    }

     

    Note: The MigrationsAssembly is where the assembly where the migrations are added. In my case the Migrations are added to the Domain project.

    Next step is to make sure the correct database schema is used. By default Entity Framework (EF) database migration will use “dbo” as the default database schema. When creating an Azure Mobile Service from the Visual Studio project template, mobile service will create a DbContext and use the name of the service as the default database schema for EF (so “dbo” will not be the default schema).

    If you locate the class that inherits the DbContext in your Mobile Service project you will see the following code:

       protected override void OnModelCreating(DbModelBuilder modelBuilder)
       {
          var schema = ServiceSettingsDictionary.GetSchemaName();
       
          if (!string.IsNullOrEmpty(schema)
             modelBuilder.HasDefaultSchema(schema);
       }

     
    The code will make sure the EF will use the name of the mobile service as the default schema.

    Note: Something to have in mind is that the name of the mobile service will be the name of the project you have created, but in Azure the name will be the name of the azure mobile service you have specified when you created the service in the Azure portal.

    This key (MS_MobileServiceName) is added to appSettings in the web.config to set the name of the mobile service:

        <add key="MS_MobileServiceName" value="MySampleMobileSerivceProjectName " />

    If you created your project in VS with a different name than the name you gave the Azure Mobile Service, you will get some problems when running your migrations. Because of the code in the OnModelCreating method that sets the EF default schema to mobile service name, all migrations you are added with the “Add-Migration” command will use the value of the key MS_MobileServiceName as the schema. That will cause a mismatch when you publish the code to Azure. If you have more than one Mobile Service environment in Azure, like Test and Prod, you can remove the code from the OnModelCreating and let EF use the default schema “dbo”. If you only have one Mobile Service environment, just make sure the MS_MobileServiceName is set to the name you gave the Azure Mobile service in Azure and skip down to where you see the code Database.SetInitializer in this blog post.

    When creating a Mobile Service in Azure, it will add a database schema to the associated database. The schema will have the name of the Mobile Service. Permissions will also be granted to this schema. The database schema that is created need to be added as part of EF database migrations, if not migrations will fail.

    Note: I will recommend you to have two Azure Mobile Service environment in Azure, one for test and one for production.

    If you have two environments, just remove the code that sets the default schema in the OnModelCreating.

       var schema = ServiceSettingsDictionary.GetSchemaName();

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

     

    Next step is to give the Azure Mobile Service database user permission to perform actions against the “dbo” schema. When a Mobile Service is created in the Azure portal, a random database use will be created and added to the associated database. This user will have its default schema set to the name of the Mobile Service. We need to make sure that user will have its default schema change to “dbo” and some other permission against the “dbo” schema, like ALTER, SELECT, UPDATE and DELETE etc.

    To make sure the database user created by Azure Mobile service gets the correct permission against the “dbo” schema, connect to the database (for example through the Microsoft SQL Server Management) and go to Users under Security of your database. You will see a user with a lot of random character and end with “LoginUser”. That is the user created by the Mobile Service. Create a new Query and write (replace <UserName> with the created Azure Mobile service user):

       ALTER USER <UserName> WITH DEFAULT_SCHEMA = dbo; 

    Then the following to give the user permissions to perform action against the “dbo” schema:

       GRANT INSERT ON SCHEMA :: dbo TO <UserName>
       GRANT SELECT ON SCHEMA :: dbo TO <UserName>
       GRANT ALTER ON SCHEMA :: dbo TO <UserName>
       GRANT DELETE ON SCHEMA :: dbo TO <UserName>
       GRANT UPDATE ON SCHEMA :: dbo TO <UserName>
       GRANT CONTROL ON SCHEMA :: dbo TO <UserName>
       GRANT EXECUTE ON SCHEMA :: dbo TO <UserName>


    The last step is to make sure the Database Migration will be added while the Azure Mobile service starts. By doing that, add the following code to the WebApiConfig.cs in the  App_Start folder of your Mobile Service project:

       Database.SetInitializer<YourEntityContext>(null);

       var migrator = new DbMigrator(new Configuration());
       migrator.Update();


    Note: There is probably already a Database.SetInitializer in you code, just replace it with the code above, just make sure you specify your name of the EntityContext.

    The SetInializer method will null as an argument will make sure no migrations will take place while there are some changes to your model the first time your code touches the EF DbContext. The code will disable that. Instead the DbMigrator will be used to update the database while the Azure Mobile Service is started.

    If everything is done correctly, you can now use manual database migrations, the key thing to get it working is to give the correct user the right permissions to a database schema.

    If you want to know when I will post a new blog post, please follow me on twitter @fredrikn

    Read more...

  • Feature enabling when using Branch by Abstraction

    Something that I haven't liked for a long time is the use of branches in a projects. I don't like the waste when it comes to merge between branches, "Merge hell". In the beginning of the project I'm in now, it took hours to do merges before a release, both handling conflicts, but also selects different changeset that should include and not include in the merge before a release. The hard part was when a branch per feature was present. Later on this was changed into one single dev branch, but still sometimes two branches may exists. The team was used to work like this from previous projects. To handle this merge hell one dedicated person handle all the merge so the team can work undisturbed (not true, they were involved when conflicts occurs). Even with a dedicated person, the problem still exists, it was just moved. The time it takes to do the merge, was there, the problem with non-disciplines people that did not following the guidelines when it comes to fixing bugs in different branches, or forgot to merge into the main branch, created problems. Wouldn't it be nice to get rid of all the merge problems, let everyone just work in the same branch? There is a way, it may not work for every projects though (sometimes a bigger change may be useful to have in a single branch, but I think it should first be avoided). The solution to the problem is what Paul Hammant calls "Branch by Abstraction".

    Read more...

  • Team Foundation Server 2012 build notification using ASP.Net Web API

    For the last three years I have helped a financial company with a business critical financial system. I have the role as an architect and coach when it comes to system design. I also spend times to make the team work more efficiently, to release new features with high quality, and maintainable code faster. So the last months I have spent a lot of time with a Deployment Process, to see how we can use Continuous Delivery. We use Visual Studio 2012 and Team Foundation Server 2012 (TFS) as our configuration system. We use gated check-ins (The goal is to use branch by abstractions, so the team work against one mainline only, to remove the "merge hell"). Even if we use gated check-ins we had to disable some acceptance tests because the time it takes for them to run. Instead we use a build that runs at lunch time and one at the night to include the acceptance tests (Those needs to be observed by the team). So far TFS have worked perfect, both for Gated check-in and Continuous Integration for the mainline. We also use TFS for a "push deployment" to our internal test and UAT environment. Everything is automated. We haven't yet "enable" the "push-deploy" against our production environment yet.

    Read more...

  • ASP.NET Web API Exception Handling

    When I talk about exceptions in my product team I often talk about two kind of exceptions, business and critical exceptions. Business exceptions are exceptions thrown based on “business rules”, for example if you aren’t allowed to do a purchase. Business exceptions in most case aren’t important to log into a log file, they can directly be shown to the user. An example of a business exception could be "DeniedToPurchaseException”, or some validation exceptions such as “FirstNameIsMissingException” etc.

    Read more...