My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
GettingStarted  
Getting Started with MigratorDotNet
Updated Feb 4, 2010 by dko...@gmail.com

Introduction

MigratorDotNet is a database versioning system much like Ruby on Rail's Migrations. Its purpose is to automate your database changes, and help keep those changes in sync throughout your environments.

Supported Databases

  • MySQL (5.0, 5.1)
  • Oracle (not well tested?)
  • PostgreSQL
  • SQLite
  • SQL Server (2000, 2005, CE)

Supported Execution Modes

  • MSBuildTarget
  • NAntTask
  • Console Application (You should be using an automation tool! :))

Overview

The basic concept here is that you create an assembly that contains your "Migrations". The Migrations are classes that derive from the Migration class. Upon deriving from Migration you will need to write the code necessary to "Up" that migration or "Down" that migration. When you migrate to that version of the database, the Up() method will be called and executing whatever database modifications need to be ran in order to bring your database to that version. When you migrate in reverse to a previous version, the Down() method will be called executing database modifications in order to undo that set of database changes.

Each Migration should be a very small incremental step in the database. Common sizes of Migrations are creating a table and adding one or more columns to a table, altering the data of a table, running a custom query with ExecuteQuery on tables. Keep your migrations as small as possible as this will facilitate easier steps between versions, much like you would in a traditional version control system such as VSS or SVN. A sample migration would be as follows:

using Migrator.Framework;
using System.Data;

namespace DBMigration
{
	[Migration(20080401110402)]
	public class CreateUserTable_001 : Migration
	{
		public void Up()
		{
			Database.CreateTable("User",
				new Column("UserId", DbType.Int32, ColumnProperties.PrimaryKeyWithIdentity),
				new Column("Username", DbType.AnsiString, 25)
				);
		}

		public void Down()
		{
			Database.RemoveTable("User");
		}
	}
}

Where the Migration Attribute indicates the order (or in version 0.8 and greater) the timestamp of this migration.

Installation and Configuration With Visual Studio

Here are the steps to add migrations to an existing solution in Visual Studio:

  1. Add a new class library project. In this example it's called Called DBMigration.
  2. Create a lib directory in your DBMigration project, and extract all the dotnetmigrator DLLs into it. You can exclude database-specific DLLs that you don't need. e.g. If you're not using Oracle, you don't need Oracle.DataAccess.dll.
  3. In your DBMigration project, add a reference to the Migrator.Framework.dll. That's the only additional reference you need in the project.
  4. create a build.proj file in your DBMigration project dir. Refer to the full example in MSBuildTarget.wiki. If you're using SQL Server, the only attribute you should need to adjust is the Connectionstring.
  5. Create your first migration.
  6. e.g. File Name: CreateUser_001.cs
    Class Name: CreateUser_001
  7. Compile and run your Migrations. The easiest way to run your migrations is to create two External Tools references for your migrations targets - one for going up, and one for going down to a specific version. Here's what the configurations look like if you're using MSBuild with .NET 2.0:
Title: Migrate Up Command: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe Arguments: build.proj /t:migrate Initial Directory: $(ProjectDir) Check the "Use Output window" box.

Title: Migrate To Version Command: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe Arguments: build.proj /t:migrate Initial Directory: $(ProjectDir) Check the "Use Output window" box Also check the "Prompt for arguments" box. You'll use that to specify which version you want to go to. (e.g. 0 for all the way back down).
Comment by nightsho...@gmail.com, Feb 5, 2009

I don't understand how to prefix C# class names with numbers. You mention using the "" prefix, but I don't see this in your example and it doesn't seem to work for me. Is this possible?

Comment by colda...@gmail.com, Mar 10, 2009

Can't classes start with a character? That might be a workaround... Or perhaps just start them all with m, for MigratorDotNet?.

Comment by danyal.a...@gmail.com, Aug 6, 2009

Can migrator.net be used to migrate data?

Comment by Kris.Wil...@gmail.com, Nov 14, 2009

2.3.4 of Rails/ActiveRecord? recently added a "rake db:seed" to the template for a new rails project. Perhaps Seed base class could be created that does something similar in this project.

Comment by rex.whitten, Jun 22, 2010

How is this useful/different from just SQL Scripting? How does this automate anything? What if you need to alter the Table? How does this save data before you alter? This looks like a tool for people who dont know sql and only C#?

Comment by strombri...@gmail.com, Jun 23, 2010

@rex.whitten: The main difference I see is, that for SQL Scripting you need to write all the boiler code yourself. If you want to execute your scripts you either have to fire up your database admin tool and do it manually or write a tool that reads in all your scripts and executes them in the right order. Also, if you have several clients with different versions of your database schema, you have to somehow track what version they have and when you update you have to make sure, that you only apply updates they don't already have. With migrator.NET you only have to specify the database connection string and the version of the schema you want to apply, the tool does all the rest for you.

As for saving data before altering a table: It doesn't (automatically). But you can write statements like "EXPORT TABLE users TO 'c:\temp'" as raw sql and let migrator.NET execute this as well.

Comment by rasmus.m...@gmail.com, Jul 28, 2010

A couple of problems with the code sample above... "ColumnProperties?" should read "ColumnProperty?", and the Up() and Down() methods need to be declared with the "override" directive, e.g.:

namespace DBMigration
{
    [Migration(20080401110402)]
    public class CreateUserTable_001 : Migration
    {
        override public void Up()
        {
            Database.AddTable("User",
                    new Column("UserId", DbType.Int32, ColumnProperty.PrimaryKeyWithIdentity),
                    new Column("Username", DbType.AnsiString, 25)
            );
        }

        override public void Down()
        {
            Database.RemoveTable("User");
        }
    }
}
Comment by rasmus.m...@gmail.com, Jul 28, 2010

Also, that's "Database.AddTable?", not "Database.CreateTable?"...

Comment by remi.des...@gmail.com, Nov 10, 2010

Is there any way to create a first migration to actually create the database? From what I've seen browsing the code (and running a few tests using ExecuteNonQuery?), it looks like the base assumption is that the database must exist.

Am I missing something?

Comment by timothy....@gmail.com, Mar 5, 2011

This is very cool, but 2 questions: (1) Is there a way to include arbitrary SQL in the Up and Down? I am a little advanced in my TSQL knowledge and I sometimes like to do things that definitely would not be supported by a database-agnostic tool like this (2) I haven't opened it up and looked at the code, but is the Database class designed in such a way that we could provide a secondary implementation that can analyze differences between VCS versions? I'd love to be able to use git bisect to analyze where something changed or broke.

Comment by jshol...@gmail.com, Jan 19, 2012

You can run arbitrary SQL scripts. I have successfully done this in the past by creating a separate directory for my SQL scripts, adding them to resource (.resx) file and then grabbing them from the resource file in my migrations. However, one thing to keep in mind here... Since it's using ADO.NET, you won't be able to execute batches like you can using SSMS or sqlcmd, as the GO keyword will have no meaning for ADO.NET. As a result, you'll just have to break-up your SQL in to multiple files and execute each one. I never found this to be that big of a deal.

I think you also hit on one of the weaknesses of the migration model. Since you aren't storing SQL scripts for your DB objects in source control, you can't really track SQL changes. IMO, that is one of the few weakness. If it was really that important to you, I'd recommend auto-generating SQL scripts for all of the objects in your DB each time you release a new version. You can then store those scripts in your VCS and compare the changes from version to version.


Sign in to add a comment
Powered by Google Project Hosting