IronRuby and the Entity Framework - Part 2.
Last time we looked at taking IronRuby to the Entity Framework ‘via the cape’ so to speak, by building our Entity Model in a C# library that we consumed from IronRuby. That previous approach was a response to the lack of support in IronRuby to directly create an Entity Model as you would with C# or VB.NET. This is not to say however that is currently the only option available.
Enter Entity SQL or ESQL as it’s become known. It is ALMOST possible to enlist the services of the Entity Framework directly from IronRuby by putting Entity SQL to work. There are a few remaining impediments however, the ability to create an Entity Model directly in IronRuby and the lack of support for Generics are the most restricting. ESQL options are therefore limited in terms of writing code in IronRuby without the support for generics, however if we take the Entity SQL route, the only thing we are required to do with respect to interop, is host an ObjectContext<T> in an assembly built with a language that will support it. Entity SQL is a SQL like language that can be used as an alternative to LINQ to Entities. ESQL is a very rich language with a great deal functionality.
Let’s step through a fairly rudimentary look at using ESQL with IronRuby. Given the simplest of Northwind Entity Models as shown here:
We would expect an ObjectContext with three ObjectQuery<T> property implementations.
public global::System.Data.Objects.ObjectQuery<Customers> Customers { get { if ((this._Customers == null)) { this._Customers = base.CreateQuery<Customers>(“[Customers]“); } return this._Customers; } } public global::System.Data.Objects.ObjectQuery<Order_Details> Order_Details { get { if ((this._Order_Details == null)) { this._Order_Details = base.CreateQuery<Order_Details>(“[Order_Details]“); } return this._Order_Details; } } public global::System.Data.Objects.ObjectQuery<Orders> Orders { get { if ((this._Orders == null)) { this._Orders = base.CreateQuery<Orders>(“[Orders]“); } return this._Orders; } }
And that’s it, where done with creating our interop library that contains our ObjectContext / Unit of Work. Having created this Entity Model in a C# or VB.NET class library that we can ‘require’, we are now ready to use Entity SQL and IronRuby to engage the Entity Framework. Let’s start off by building a helper class to create the ObjectContext for us:
require ‘System.Windows.Forms, Version=2.0.0.0, ‘ + ‘Culture=neutral, PublicKeyToken=b77a5c561934e089′ require ‘D:/simon.segal/Local Working/Org.Techavalanche.IronEntities’ + ‘/Org.Techavalanche.EntityLibsForRuby/bin/Debug’ + ‘/Org.Techavalanche.EntityLibsForRuby.dll’ require ‘System.Data, Version=2.0.0.0, ‘ + ‘Culture=neutral, PublicKeyToken=b77a5c561934e089′ require ‘System.Data.DataSetExtensions, ‘ + ‘Version=3.5.0.0, Culture=neutral, ‘ + ‘PublicKeyToken=b77a5c561934e089′ require ‘System.Data.Entity, Version=3.5.0.0, ‘ + ‘Culture=neutral, PublicKeyToken=b77a5c561934e089′ require ‘System.Core, Version=3.5.0.0, ‘ + ‘Culture=neutral, PublicKeyToken=b77a5c561934e089′ class EntitySqlHelper def initialize end def get_northwind_context providerName = “System.Data.SqlClient”; serverName = “boomer”; databaseName = “Northwind”; #Initialize the connection string builder for the #underlying provider. sqlBuilder = System::Data::SqlClient:: SqlConnectionStringBuilder.new #Set the properties for the data source. sqlBuilder.DataSource = serverName; sqlBuilder.InitialCatalog = databaseName; sqlBuilder.IntegratedSecurity = true; #Build the SqlConnection connection string. providerString = sqlBuilder.ToString(); #Initialize the EntityConnectionStringBuilder. entityBuilder = System::Data::EntityClient:: EntityConnectionStringBuilder.new #Set the provider name. entityBuilder.Provider = providerName; #Set the provider-specific connection string. entityBuilder.ProviderConnectionString = providerString; #Set the Metadata location. entityBuilder.Metadata = “res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl” #get the connection string con = entityBuilder.ToString() #set up the ObjectContext session = Org::Techavalanche:: EntityLibsForRuby::NorthwindEntities.new(con) end end
Next comes the interesting part, writing some code to actually use the ObjectContext<T> and fetch some data.
#basic use of Entity SQL to obtain a #result set using the Entity Framework begin h = EntitySqlHelper.new #gets the ObjectContext ctx = h.get_northwind_context #enumerate the Customers property of the context #directly. Customers is an ObjectQuery<T>, so we #do have some ability to use types that are generics #but we cant new any up explicitly as yet in IR ctx.Customers.each {|cust| puts cust.CustomerID} #lets have a look at the query string puts ctx.Customers.ToTraceString #now for some Entity SQL #create a connection connection = System::Data::EntityClient:: EntityConnection.new(ctx.Connection.ConnectionString) #open a connection connection.Open #write some Entity SQL statement stmt = “select c.CustomerID, c.CompanyName “ + “from NorthwindEntities.Customers as c” #new up an EntityCommand cmd = System::Data::EntityClient::EntityCommand.new(stmt, connection) #get a DbDataReader to enumerate the results cmd_reader = cmd.ExecuteReader(System::Data:: CommandBehavior.SequentialAccess) #print out the results from the query while cmd_reader.Read puts “Company ID: “ + cmd_reader.GetValue(0) + ” “ + “for Company Name: “ + cmd_reader.GetValue(1) end end
Some things I would like to note about the code above:
- Despite the lack of support for Generics, we do have support to new up Generic constructed types from an interop library that we write in other .NET languages.
- ObjectQuery<T> implements IEnumerable<T> and has also benefited from having the implementation of the .each method we would expect from a collection.
- Whilst lacking in the fluency of LINQ to Entities, Entity SQL does provide a reasonable solution in the short term for anybody who wants to include working with data as they spike their way to familiarity with IronRuby or perhaps your bold enough to use it in production scenarios at this early stage? Perhaps not?
The while loop at the bottom of code block above, produced this Ruby Console output in Visual Studio.
So, that’s a fairly rudimentary look at ESQL leveraged from IronRuby. The code from this post can be found here. Given my predilection toward the Entity Framework and my growing interest in IronRuby, I will continue this series with more up to date examples when (if) IronRuby begins to add the required support for this new data access platform.
Finally, I should mention that I am (again) using the FREE personal edition of Sapphire in Steel which plugs into Visual Studio 2008 quite nicely.
1 comment








