Sunday, October 31, 2010

Using IronRuby at Work: Part 2 – Using AssemblyBuilder and System.Reflection.Emit to create a .NET Assembly.

I will be giving a talk on this subject at this subject on November 6, 2010 at the Triangle .NET User Group’s RDU Code Camp

This is the second post in a three part series in which I will discuss how I used IronRuby to make my life easier.  In this post I’m going to discuss how IronRuby was used to generate a .NET Assembly.

All source files can be downloaded from here

Generating Non-EF Models

Now that I can make queries against the database I want to make non-EF models that I can use to move data from the data access layer to the presentation layer.  Some may think this is over-kill but I like to keep EF out of my presentation layer.  Plus, if I can generate these models it doesn’t take much to have this extra layer.

The code generation process is managed by a class called CodeGen.  The CodeGen class has methods to generate the models and the domain classes.  CodeGen’s initialize method (ruby class’ constructor) there are three important objects created: GenerateAssembly, ModelGenerator and ElementsService.  The GenerateAssembly class is where the actual assembly is created.  The  initialize method creates the dynamic assembly and a module are created with these two calls:

The first call creates the dynamic assembly by passing in the assembly name and version information which is stored in the @asm variable.  The AssemblyBuilderAccess.RunAndSave is used to indicate that we want the ability to run the code as well as save it to the file system. The second call creates the module for the assembly.  I will use the @mod_builder object to create our model classes for our assembly.

After I have a CodeGen object I will call the create_models method.

The create_models method uses the ElementsService class (discussed in the first post of this series), to retrieve all active views using LINQ in my IronRuby script.  For each view returned a call to create_model is made.

The create_model method is where we actually start generating CIL code.  The @model_gen.generate method drives the actual model class creation and adds it to the assembly.  It returns the actual CLR type of the new model and an array that contains the names of all domain level classes that will be used to drive the domain class generation process.  Let’s get into the actual generation of the model classes.

The ModelGenerator class

The ModelGenerator.generate method is called with two parameters.  The first parameter is the name of the class to create and the second one is an array of properties to create.  

The first line of code starts the generation by calling GenerateAssembly.define_class method which returns a TypeBuilder object that represents the class.  The GenerateAssembly.define_class method looks like this:

The define_class parameters are pretty straight forward.  The first parameter is the name of the class to be created.  The second parameter contains the name of the interface the class is going to implement.  If no name is given it will be set to nil (null in C#). The @mod_builder variable is a ModuleBuilder object which I will use to create the model class.  Calling the DefineType method creates a representation of the model class which is returned in a TypeBuilder object that we will be used to create the class’ properties. 

When the define_class call returns we will create the properties.  Creating properties is a little more involved then creating a class.  The properties will be created using the ModelGenerator.create_property method.  The create_property method takes the TypeBuilder object that represents the class, the name of the property and the CLR type of the property.  The last parameter is optional and I will go with the default.

The first line creates the private field that will store the value of the property using the TypeBuilder to call the DefineField method.  I keep the returned FieldBuilder object so I can use it in the body of the setter/getter methods. 

Next I will create the property by calling TypeBuilder.DefineProperty.  The parameters are the name of the property, attributes that describe the property, the CLR type and the parameter types.  Since I do not have parameters in our properties I set it to nil.  The returned PropertyBuilder is stored so I can use it to associate the getter/setter methods to it.

The next step is to create the getter method by calling TypeBuilder.DefineMethod object.  After the DefineMethod call I can start generating CIL, also known as MSIL.  The DefineMethod call returns a MethodBuilder object that we use to get an ILGenerator object which is how I will create the body of the getter method.  The generation is done by making calls to the Emit method.

The first Emit call loads the argument at index one onto the stack.  The next line finds the value of a field in the object whose reference is currently on the evaluation stack, in this case it is the private field that I created first.  The last line adds the return statement to the getter.  As you can see there isn’t much to setting up the getter method.

The process for the setter is similar to the getter except for two things.  The first difference is setting up the parameters for the setter.  The second is to set the value of the private field.  The parameters for the setter are created by these lines. 

Since I am using IronRuby I had to create a generic list of the type Type and add the type parameter to the list. There may be another way to do it but I don’t know any other way to get a CLR array of Type.  Just prior to calling the DefineMethod I convert the list to an array using the .NET generic list’s ToArray method and pass it to the the DefineMethod as the last parameter.  This sets the setter method’s parameter type.

The second difference is the section of code that store the parameter’s value in the private field.  The Ldarg_1 line loads the parameter onto the stack.  The next line sets the value our private field to the value of the parameter.  All the rest of the code for the setter is the same as the getter method.

Finally I relate the getter and setter methods to the property by making these two calls below.

Back to ModelGenerater.generate

After creating all the properties for the model the next thing we need to do is to create the Type for the model’s class. Which is done by making the GetType call below.

Once the GetType method is called I am done with the creation of the model’s class.  After all of the models are created the script writes the new assembly out to the file system using the AssemblyBuilder object that was created in the first line of the CodeGen class’ initialize method.

Summary

After reading the information from the database I was able to convert that data into a model classes in CIL without much work.   I can now take information from 3 database tables and generate models for the classes we need in a few seconds.  Now that I have the generated models and EF entities I am almost ready to start using the data.  In Part 3 of this series I will go over how I create the domain layer classes using the CodeDom.

You can download the IronRuby and C# code for this series from here.

Thursday, October 21, 2010

Microsoft turns IronRuby and IronPython over to new Leadership

You can read the official announcement here.  In addition to the turnover they now have visual studio tools for IronRuby.  The tools can be found here.  Install the IronRuby 1.1.1 it has the tools for visual studio. I haven’t used them yet but thought I’d let you know.

image

Getting Rails 3 Up on Windows Connecting to SQL Server

Our web group is starting a few test projects on Ruby on Rails for some of our tools.  Our group works in the windows environment with both client/server and ASP.NET MVC apps.  This morning I went through the process of getting two machines set up to do Rails development and I thought I’d write up a quick post to pass along what I learned.  First off I want to say it wasn’t as painful as I thought.  Here is what I did to get rails 3 up and running against SQLServer 2005 and 2008.  My environment is windows 7 64 bit.  I also installed it on Windows 7 32 bit.  For the purposes of this post I will walk you through my install on the 64 bit OS.
I am assuming you have a clean (no ruby installed) machine and a new/clean database to work with.  If you already have ruby and some gems installed you can skip some of the steps.  However, you must have the RubyInstaller version of the interpreter installed for this to work.  With that, here are the steps to running rails 3 on Windows and SQL Server!

Step 0 – Setting up a DSN

For 32 bit Windows:  Go to Control Panel > System And Security > Administrative Tools > Data Sources (ODBC) and create a System DSN (I’m not sure if It has to be a System DSN but that’s what I did).  For the purposes of this blog post I choose the With Windows Integrated Authentication option for authentication.
image
For 64 bit Windows:  First and foremost, if you setup your DSN following the 32 bit approach you will not be able to connect to the database with rails.  You will receive an error like this: 
ERROR [IM014] [Microsoft][ODBC Driver Manager] The specified DSN contains an
architecture mismatch between the Driver and Application
The above error is due to the fact that you have set up a DSN with the 64 bit version of the Data Sources applet.  After a little quick Google search I found this fix on Stack Overflow.  Basically, you have to run the version at c:\windows\sysWOW64\odbcad32.exe to setup the DSN. After the DSN configuration lets move on to install ruby and all the necessary gems.

Step 1 – Installing Ruby
The first thing you need to do is install ruby using the RubyInstaller which can be found at RubyInstaller.org (download link for 1.9.2).  This method of installing ruby is required or you will not be able to do step 2. 

Step 2 – Install the RubyInstaller DevKit

After you have installed ruby the next step is to download the devkit from from the rubyinstaller.org here.  Follow these instructions explicitly and you will be ready to start installing the database related gems.

Step 3 – Installing the Database Related Gems

Open a command prompt if you do not already have one open and run the following commands:
  1. gem install ruby-odbc 
  2. gem install activerecord-sqlserver-adapter

Step 4 – Install Rails and Create a Test Application

Once you have the DB gems installed the next step is to install rails itself:
  • gem install rails

When the install is complete change and/or create a directory where you want to create the test application.  Once you are in the directory where you want the application run the command:

  • rails new rails_on_win

The above command creates a new application I’m not going to get into that here you can find out more about the architecture of a rails app here.


Step 5 – Configuring the Database Connection (config\database.yml)


Next, change into the rails_on_win,directory or whatever name you used to create the application in step 4.  Open the config\database.yml file in your favorite editor.  Change the development section to be similar to this: image

Change the DSN setting to whatever you called your DSN in step 0.  If you set up the default database in DSN or the DB user has one set you can get rid of the database setting.  if we were using a SQL Server account for authentication we would need to add username and password settings to the connection information.  Since we chose the integrated authentication we do not need to worry about it.  When you are done save and close the file.



Step 6 – Configuring and Installing the Gems in our App


Now that we have our database configuration complete the last thing we need to do before firing up the app is to update our Gemfile.  It can be found in the root directory of the app.  Open up your editor and load the Gemfile.  We need to add two entries:


  • gem ‘ruby-odbc’
  • gem ‘activerecord-sqlserver-adapter’


I added them after the gem ‘rails’, ‘3.0.1’ entry I’m not sure if order matters I’m just working under the assumption that it does.  After adding the two gems if you do not have Sqlite3 installed you will need to comment out the line: gem ‘sqlite3-ruby’.  Save and close the file.  We are now ready to fire up our app!


Step 7 – Starting the Application and Checking the Settings


In the application’s root directory run the command:

rails server 

It takes a little bit for the development server to start up but when it does you should see output similar to this:


image



Now we are ready to hit the web site.  Start up a browser and enter http://localhost:3000 you should see a page like this  (I’m just showing the top portion of the page):


image
If you see this page you are halfway there.  Next, click on the ‘About your application’s environment’ link.  You should see information in a yellow box that lists the configuration settings for your application.  The setting I want to point out is the database section towards the bottom of the page.  You should see:
image
If there is a setting that is incorrect or some other problem instead of the detailed setting description you will see an error message.  I ran into the one I mentioned in step 0 when I used the 64 bit DSN configuration applet. I received this error message when I misspelled the name of my DSN:

IM002 (0) [Microsoft][ODBC Driver Manager] Data source name not found and no
default driver specified

Step 8 – Create the Database

If you saw the page with all the settings information then you ready to get started!  At the same command prompt run:

rake db:create

After the successful completion of that command you should see a table called schema_migrations in your SQL Server database.

That’s It!

Now you are ready to start building rails apps in a Microsoft environment.

Sources

The two sources below in addition to the Rubyinstaller.org site  made this process extremely easy.  I had heard many people say it was hard to get rails going on windows.  I may run into that when I move out of the development phase but for now, it isn’t that bad. 

Wednesday, October 20, 2010

Using IronRuby at Work: Part 1 – Using EF with IronRuby to retrieve data

I will be giving a talk on this subject at this subject on November 6, 2010 at the Triangle .NET User Group’s RDU Code Camp

This is the first post in a three part series in which I will discuss how I used IronRuby to make my life easier.  In this post I’m going to discuss how IronRuby was used with Entity Framework 4 to retrieve data from a SQL Server database.

The Project – Use IronRuby to Produce a .NET Assembly

Our project consists of using 3 db tables to generate models and domain layer classes.  I chose to use IronRuby as the main language and to product an actual assembly that would contain the models and service classes. The goal of the project is to generate model and domain level code using 3 database tables.

The DB Tables

The three tables are elements, elements_to_views, and views.  The elements table holds all of the fields that will be needed to meet the requirements for this project.  The table’s main purposes is to satisfy a third-party requirement for documentation that means this table will always be up to date.  We will use this table as the main driver in the code generation process.  The views table is a way to group the elements into a set and we will use this to create the model classes.  Despite the name of this table these classes may or may not be used in the UI.  The elements_to_views table is used to relate the elements to their views which in the code means that the elements associated with a view will be a property in the view’s class. 

image

After setting up the EF entities I tried to interact with them directly from within the IronRuby script without success.  Since I’m new to IronRuby I’m not sure if it was something I was doing wrong or if it is a limitation, so instead of wasting a lot of time on figuring out I decided to create a Repository and ElementsService classes in C# to wrap the classes so I can get on with my IronRuby experimentation. (I’m not going to show the C# code here since I’m concentrating on IronRuby.  If you want to check out the code visit the the bitbucket project.)

Jumping into the IronRuby code…

Let me preface the rest of this post by saying I am a Ruby newb so please let me know if I”m breaking ruby coding practices or anything along those lines.  I’m learning it and loving it!  Any guidance would be appreciated.

After I finished the service class I was ready to start writing the IronRuby code.   My first class was a wrapper for the for the ElementsService C# class which I named….ElementsService.  Here is the code for the class:

What I’d like to discuss first are the two require lines at the top of the file.  The require ‘mscorlib’ brings in core Microsoft library.  The second is a reference to the assembly that contains the EF, Repository and ElementsService class.  The IRCDemo.Data assembly is in the same directory as the elements_service.rb file.Once those two requirements are loaded we have both assemblies at our disposal.  This means that any method that is available to you in C# is also available to you in IronRuby. 

Once we have the two assemblies loaded the script initializes the data context in the initialize method. The constructor in both Ruby and IronRuby classes.  The rest of the class just wraps calls to the C# version of the ElementsService class except for the get_properties method, which I will discuss in a later in the series.

Enough already, show me the data!

So now that we have the data access code in place lets write a script that gets all the data from the elements table.

Not much to this script but that’s the way I like it.  After loading the elements_service file the script instantiate an ElementsService object.  The next call is to the get_elements method which simply makes a call to the C# ElementsService.GetElements method.  When the results of the call are returned I loop through and print out the contents of the element record.  Once the data has been printed out the dispose method is called to ensure that the data context to ensure we clean up after ourselves.

To run the script above at the command prompt in the directory where the script exists enter:

ir blog.rb

will will produce output like this:

image

Summary

This is a good ending point for the first post in this series.  In this post we’ve laid out the foundation for the next two posts.  We’ve discussed how to interact with .NET assemblies from IronRuby.  In Part 2 we will take the .NET interoperability by using System.Reflection.Emit to create an assembly that contains the .NET model classes. 

You can download the code from here.

If You are Wondering Why I did this..

Why do this in IronRuby?  I’m in the process of teaching myself Ruby and Rails and the more I learn the more I like it.  So I’m looking for any excuse to introduce Ruby into our strictly MSFT environment.  Since this project is a proof of concept I thought it would be a nice starting point.

Addendum

I spent about five minutes attempting to get ActiveRecord to work with my SQL Server database without success that is why I went with the EF approach.  If anyone can point me to a resource that will help me get ActiveRecord up and running with SQL Server I’d appreciate it. Also, if there is anyone who has been successful in loading an EF generated model please let me know how you did  it.

Saturday, October 2, 2010

It has been awhile…

Quite some time has gone by since I last posted an article on my blog.  Part of the reason is I was on vacation for a few weeks, another reason is school has started back up, and yet another reason is just pure laziness. 

In addition to those lame excuses I’ve been working on getting up to speed with Ruby.  I’ve dabbled with Ruby off and on for a little bit now.  I’ve used ruby to do a proof of concept here at work.  The POC worked out but was converted over to C# and MVC because our production environment set up.

In the next week I will start blogging about my experiences with IronRuby.  The first post will be around how I’m using IronRuby and Entity Framework 4 to access a MS SQL Server DB.  I’ll follow that up with either more details on that project or how I’m using RSpec and Cucumber to test our .NET based web applications.