Amptools.Net

simplify your life.

ado.net

The trouble with porting migrations and railties into other languages.

No Gravatar

I’ve been toying with API design for solid and simple with Ado.Net to build migrations on top of and possibly layer for building ORMs on. Ironically, Rob Conery, of Subsonic fame, just posted a page (or blog) about migrations in .net and subsonic in general.

The Problem(s).

Database agnostic scripting in C# and PHP and executing sql statements without having to use a heavy ORM in C#.

Obviously, Rails makes a good run at these problems with active record’s built in migrations that everyone and their mother (or at least their co-workers) tries to mimic.   However C#, PHP, and other C style languages lack that Ruby Meta Programming magic.

So why not just include active record into a project that isn’t rails?  This might be doable with Iron Ruby’s release on the horizon. Unfortunately the cost of adding another language to a project is not always justifiable (as some rubyist zealots tend to forget ;) .

So why not just port the awesome library?

After much time over the last year or so, I’ve come to the conclusion that porting libraries from other languages often comes with delusions of grandeur.  Especially when the languages differ on key features.

Ruby and in some ways Javascript, have a much better mechanism for the portability and mixing in methods. Ruby itself has the ability to create powerful readable Domain Specific Languages that other modern languages will not be able to copy.

You tend to see possible extra noise or reduced flexibility when you compare something like Migrator.Net

[Migration(20080805151231)]
public class AddCustomerTable : Migration
{
    public override void Up()
    {
         Database.AddTable("Customer",
             new Column("name", DbType.String, 50),
             new Column("address", DbType.String, 100),
             new Column("age", DbType.Int32)
        );
    }

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

to Rails Migrations.

class 20080805151231_AddCustomerTable > ActiveRecord::Migration
  def self.up
    create_table :customer do |t|
        t.string   :name,     :limit => 50
        t.string   :address,  :limit => 100
        t.integer  :age
   end
 end 

  def self.down
    drop_table :customer
  end
end

The biggest issue I see though is sometimes throwing out the baby with the bathwater by not using some of the same naming conventions because the languages do differ.

Possible Solutions Or Ideas

At least when it comes to C# 4.0 it shouldn’t be too hard to create a .Net library and then create a thin DSL layer in Ruby through Iron Ruby to make calls to the .Net lib.  That coupled with some form of code generation could give you a decent programing work flow.

Another option is to port key features from Rails, adapt to the language that your working in, but at least keep some kind of consistency in naming.

Or you could do a hybrid. That way you have the ability to create a readable DSL in projects that can allow for this or let you fall back to your native language if it doesn’t.

It is still ugly and verbose, but at least it follows in some proximity to its ported counter part.

[Version(20080805151231)]
public class AddCustomerTable : Migration
{
  public override void Up()
  {
    CreateTable("Customer", (t) => {
      t.String   ("name",     (c) => { c.Limit = 50; });
      t.String   ("address",  (c) => { c.Limit = 100; });
      t.Integer  ("age");
    });
 }

 public override void Down()
 {
    DropTable("Customer");
 }
}

And it shouldn’t be hard to build on an underlying API. If done right, you could use the DLR for Ruby or even Python for scripting access or creating that thin readable DSL layer.

It would have probably been cleaner to use optional parameters, but ‘default’ and ‘null’ are keywords in C# and adding @ to keywords for variables can distract from readability.

Another path is to create something new that adapts to your language but does the same thing in principle similar to what Rob partly did for Subsonic 3.0’s migrations.  Porting could be trying to put a square peg in a round hole. So its time to create that peg that fits.

I’ll have some follow up posts that cover ideas on the other areas of being able to script sql in C# with Ado.Net as well as experimental APIs and concepts.  If you got any comments, leave em.

Tags: , , , , , ,