Archive for October, 2008
IronRuby with LINQ To SQL (kinda)
I have been playing around with IronRuby a bit just of late and I was curious to see whether it was at a stage where it was working with LINQ To SQL. It was clear from the outset that using LINQ To SQL in the most common way (with full UI experience) in VS.Net was simply a silly thing to expect and it became immediately apparent that any benefit of IEnumerable<T> or IQueryable<T> was out the window also. Given that that any attempt to access IEnumerable<T> from any instance of Table<T> was for now a journey into folly, I tried briefly to circumvent that approach and see if I could POCO my way to an outcome with Mapping files. Listing 1.0 shows this unfortunately doomed venture.
Attempt No # 1.0
First the C# POCO Entity class required in the RubyCustomer library.
using System; namespace Org.TechAvalanche.Orm.Tests.Domain { public class Customer { private string _CustomerID; private string _CompanyName; private string _ContactName; private string _ContactTitle; private string _Address; private string _City; private string _Region; private string _PostalCode; private string _Country; private string _Phone; private string _Fax; public Customer() { } public string CustomerID { get {return this._CustomerID;} set {this._CustomerID = value;} } public string CompanyName { get {return this._CompanyName;} set {this._CompanyName = value;} } public string ContactName { get {return this._ContactName;} set {this._ContactName = value;} } public string ContactTitle { get {return this._ContactTitle;} set {this._ContactTitle = value;} } public string Address { get {return this._Address;} set {this._Address = value;} } public string City { get {return this._City;} set {this._City = value;} } public string Region { get {return this._Region;} set {this._Region = value;} } public string PostalCode { get {return this._PostalCode;} set {this._PostalCode = value;} } public string Country { get {return this._Country;} set {this._Country = value;} } public string Phone { get {return this._Phone;} set {this._Phone = value;} } public string Fax { get {return this._Fax;} set {this._Fax = value;} } } }
coupled with the following LINQ To SQL Mapping file
<?xml version=”1.0″ encoding=”utf-8″?> <Database Name=”Northwind” xmlns=”http://schemas.microsoft.com/linqtosql/mapping/2007″> <Table Name=”Customers” Member=”Customer”> <Type Name=”Org.TechAvalanche.Orm.Tests.Domain.Customer”> <Column Name=”CustomerID” Member=”CustomerID” DbType=”NChar(5) NOT NULL” IsPrimaryKey=”true” CanBeNull=”false” UpdateCheck=”Never” /> <Column Name=”CompanyName” Member=”CompanyName” DbType=”NVarChar(40) NOT NULL” CanBeNull=”false” UpdateCheck=”Never” /> <Column Name=”ContactName” Member=”ContactName” DbType=”NVarChar(30)” CanBeNull=”true” UpdateCheck=”Never” /> <Column Name=”ContactTitle” Member=”ContactTitle” DbType=”NVarChar(30)” CanBeNull=”true” UpdateCheck=”Never” /> <Column Name=”Address” Member=”Address” DbType=”NVarChar(60)” CanBeNull=”true” UpdateCheck=”Never” /> <Column Name=”City” Member=”City” DbType=”NVarChar(15)” CanBeNull=”true” UpdateCheck=”Never” /> <Column Name=”Region” Member=”Region” DbType=”NVarChar(15)” CanBeNull=”true” UpdateCheck=”Never” /> <Column Name=”PostalCode” Member=”PostalCode” DbType=”NVarChar(10)” CanBeNull=”true” UpdateCheck=”Never” /> <Column Name=”Country” Member=”Country” DbType=”NVarChar(15)” CanBeNull=”true” UpdateCheck=”Never” /> <Column Name=”Phone” Member=”Phone” DbType=”NVarChar(24)” CanBeNull=”true” UpdateCheck=”Never” /> <Column Name=”Fax” Member=”Fax” DbType=”NVarChar(24)” CanBeNull=”true” UpdateCheck=”Never” /> </Type> </Table> </Database>
and now our IronRuby attempt to talk DIRECTLY LINQ To SQL.
require ‘mscorlib’ require ‘System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′ require ‘System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′ require ‘System.Data.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′ require ‘RubyCustomer, Version=0.0.0.0, Culture=neutral, PublicKeyToken=c1aba19d9dedea39′ begin #get the mapping into a stream stream = System::IO::StreamReader.new(“C:\\Users\\simon.segal” + “\\Desktop\\IronRuby\\ironruby\\bin\\DomainMapping.xml”) mapping_file = System::Data::Linq::Mapping::XmlMappingSource. FromStream(stream.BaseStream) #new up a DataContext with our mappings db = System::Data::Linq::DataContext.new(“server=localhost;initial “+ “catalog=Northwind;user id=sa;password=supremo”, mapping_file) #new up a POCO customer from my C# library cust = Org::TechAvalanche::Orm::Tests::Domain::Customer.new #not sure if typeof works in IronRuby cust_type = cust.GetType() #load the table of customers from northwind custs = db.GetTable(cust_type) #tried to get enumerator but .Current gets a method error #and so ends our journey list = custs.GetEnumerator() puts “The call to GetEnumerator returned a “ + list.GetType.ToString() currentCust = list.Current rescue Exception => ex puts “someone is missing a method!” + ex.to_s #just to prove that it’s a Table<Customer> puts “Just to show that we did get as far as “ + “getting the Table<Customer> : “ + custs.ToString() end
Which yields the following output from standard IO (click to see full view):
So as you can see here, we get close but no cigar. Ready to give up - damn, not yet! Lets move all the LINQ To SQL code into our custom library and call it from IronRuby - that should work? We already had a POCO in our library referenced above (see the require ‘RubyCustomer’). So here we go.
Attempt No # 2.0
As a jumping off point for attempt # 2, I thought it might be time to check out Ruby In Steel, a third party integrated UI platform for VS.NET and IronRuby. I wanted to be able to keep my C# library with the LINQ To SQL code and the IronRuby consumer code in a single solution if possible and I was looking for a bit of holiday from writing Ruby Code in SciTE and NetBeans, therefore looking at Ruby In Steel had been on the agenda for a while so I figured now was as good a time as any. This gave me a more instantly gratifying experience in developing a Windows Form to present my LINQ To SQL data as well:
As you can see I have my C# project and my IronRuby project coupled together in a single VS.Net solution and whilst Ruby in Steel is not quite as stable or fully featured as you would expect it to be when IronRuby makes it’s official debut, it certainly helped speed things up quite a bit.
The LINQ To SQL code consisted of a run of the mill repository, POCO and mapping file (the entity itself remained as is - see above Customer Class).
using System.Data.Linq; using System.Linq; namespace CsharpLinqToSqlForIronRuby { public class CustomerRepository { private readonly DataContext _context = null; public CustomerRepository(DataContext ctx) { _context = ctx; } public Customer[] All() { Customer[] retCustomers = null; using (_context) { retCustomers = _context.GetTable<Customer>().ToArray(); } return retCustomers; } public Customer FindById(string custId) { Customer retCustomer = null; using (_context) { retCustomer = _context.GetTable<Customer>(). Where(c => c.CustomerID == custId).Single(); } return retCustomer; } } }
On the IronRuby side of things, we dialled up a class to handle calling our C# Repository library:
require ‘mscorlib’ require ‘System.Core, Version=3.5.0.0, ‘ + ‘Culture=neutral, PublicKeyToken=b77a5c561934e089′ require ‘System.Windows.Forms, Version=2.0.0.0, ‘ + ‘Culture=neutral, PublicKeyToken=b77a5c561934e089′ require ‘System.Data.Linq, Version=3.5.0.0, ‘ + ‘Culture=neutral, PublicKeyToken=b77a5c561934e089′ require ‘D:/simon.segal/LocalWorking/IronRubyProofs/’ + ‘IronRubyWithLinqToSqlForms/IronRubyWithLinqToSqlForms/’ + ‘CsharpLinqToSqlForIronRuby.dll’ class CustomerController def GetAllCustomers #get a stream of the mapping file stream = System::IO::StreamReader.new(“D:\\simon.segal\\” + “LocalWorking\\IronRubyProofs\\” + “IronRubyWithLinqToSqlForms\\” + “IronRubyWithLinqToSqlForms\\DomainMapping.xml“) #set the mapping source mapping_file = System::Data::Linq::Mapping::XmlMappingSource. FromStream(stream.BaseStream) #new up a DataContext with our mapping db = System::Data::Linq::DataContext.new(”server=localhost;initial ” + “catalog=Northwind;user id=sa;password=supremo”, mapping_file) #new up our repository cust_repos = CsharpLinqToSqlForIronRuby::CustomerRepository.new(db) #get all the customers custs = cust_repos.All() #print customers to the console window (in debug) custs.each {|cust| puts cust.CompanyName} return custs end end
And what we needed now was an IronRuby WinForm to do the presentation work and data binding for us:
require ‘Form1.designer.rb’ require ‘CustomerController.rb’ class Form1 #form load def Form1_Load(sender, e) end #button click event handler def button1_Click(sender, e) controller = CustomerController.new self.comboBox1.DisplayMember = “CustomerID” self.comboBox1.ValueMember = “CustomerID” custs = controller.GetAllCustomers.each {|customer| self.comboBox1.Items.Add(customer)} self.lstCustomer.DataSource = custs self.lstCustomer.DisplayMember = “CustomerID” self.lstCustomer.ValueMember = “ContactName” end #combo box selected index changed handler def comboBox1_SelectedIndexChanged(sender, e) cust = self.comboBox1.SelectedItem self.textBox1.Text = cust.CompanyName self.textBox2.Text = cust.ContactName end #list customer selected index changed handler def lstCustomer_SelectedIndexChanged(sender, e) cust = self.lstCustomer.SelectedItem self.textBox1.Text = cust.CompanyName self.textBox2.Text = cust.ContactName end end
Give your fluent Interface a face - [Part 1]
I am thinking. Stop that you say? Seriously, I have been wondering about combining a fluent interface with a some VS.Net VSX visual DSL tooling. I am currently working a small internal domain specific language and it occurred to me that rather than leaving the only method of access to the DSL as raw code, that perhaps by building out some visual entities around the entities expressed through the DSL, I might just be able to build a platform and not just the DSL on it’s own. So if we have code like:
3.Month.Old.Documents(“Contract”)
created by a designer like experience along of the lines of this:
Just having preliminary thoughts about this at the moment and I can already see that the vocabulary of DSL runs the risk of being influenced by the UI design in way that obscures and corrupts its meaning. For example should it read:
//makes sense 3.Day.Old.etc //seems awkward and clunky 3.Day.InFuture
A quick revision to the Fluent Interfaces and Designer and we might get this:
Ok so we can start to think about all sorts of things when it comes to the readability of the language underneath the designer but my next question is what about constraints? Should we have any? Does it feel right to leave the user the ability to define a design that would produce this:
3.Years.Now.etc.etc
But I don’t want to start building constraints around what would amount to business logic concerns now, or do I? A lot more thought is required on this whole topic I think.
No commentsGOF Series: Episode #3 [The Singleton - aka the devils work]
Next in the series we continue with the creational group of patterns and move onto the singleton pattern.
What is the singleton and how does it work?
- A globally available single instance of class, where only one single instance can exist at any given point in time.
- Maintains and instantiates itself across multiple threads at any given time.
- All public methods and members are accessed via the single instance.
- Constructed instances cannot be created outside of the singleton class. This is achieved by using a private constructor only accessible from the singleton itself.
Is the singleton the devils work?
- They promote tight coupling between objects and components – consumers know exactly where to get a copy of their collaborating classes.
- Remember that coupling is a measure of dependencies.
- Cannot be easily substituted ala dependency injection.
- Inherently lack scale.
- Difficult to unit test.
Singleton example in C#
Given this singleton below:
public sealed class Singleton { static Singleton _instance = null; static readonly object _padlock = new object(); static List<int> _ThreadSafeCounterList = new List<int>(); static readonly Guid _instanceId = Guid.NewGuid(); private Singleton() { } public static Singleton Instance { get { lock (_padlock) { if (_instance == null) { _instance = new Singleton(); } return _instance; } } } public List<int> ThreadSafeCounterList { get { lock (_padlock) { return Singleton._ThreadSafeCounterList; } } set { lock (_padlock) { Singleton._ThreadSafeCounterList = value; } } } public Guid ID { get { return _instanceId; } } }
and this program:
class Program { static AutoResetEvent evt; static void Main(string[] args) { Console.WriteLine(“Enter a key to begin the singleton workers”); Console.ReadLine(); const int countup = 2000; for (int x = 0; x <= countup; x++) { //new up a background worker BackgroundWorker bg = new BackgroundWorker(); //wire up the work handler delegate to do the computation bg.DoWork += new DoWorkEventHandler(bg_DoWork); //when x has reach the upper boundary of the loop //subscribe to the event that fires when the //work handler has completed its work (will subscribe) //to the last thread dialled up via the bg worker if (x == countup) { //last bg worker thread - subscribed to its //completed event to signal an end bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted); } //run up a thread bg.RunWorkerAsync(x); } //wait until blocks the current thread (main thread) //until signaled - will pause here.. evt = new AutoResetEvent(false); evt.WaitOne(); } static void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { Console.WriteLine(“Start reading of the list in “ + “the order the items were written.”); Console.ReadLine(); //loop the list of integers and print //them in order they were inserted for (int i = 0; i < Singleton.Instance. ThreadSafeCounterList.Count; i++) { Console.WriteLine(Singleton.Instance. ThreadSafeCounterList[i].ToString()); } //signal to the user the total processing figures Console.WriteLine(“TOTAL added to Thread safe List is : “ + Singleton.Instance.ThreadSafeCounterList.Count.ToString()); //pause for user entry Console.ReadLine(); //signal to the main thread to continue //and therefore exit. evt.Set(); } static void bg_DoWork(object sender, DoWorkEventArgs e) { System.Threading.Thread.Sleep(10); Console.WriteLine(“Added “ + e.Argument.ToString() + ” by thread with hashcode “ + Thread.CurrentThread.GetHashCode() + “\tto instance ID:\t” + Singleton.Instance.ID.ToString()); //add the integer to the list Singleton.Instance.ThreadSafeCounterList.Add((int)e.Argument); //give back a time slice so the other threads get a piece System.Threading.Thread.Sleep(10); //write out to the window when you find //the same integer that was just added //because a time slice was given back to //the OS task scheduler, another thread //may be processing, so the found integer //and thread hashcode will not necessarily //print in order. Console.WriteLine(“Found “ + Singleton.Instance. ThreadSafeCounterList.Find( delegate(int findInt) { if (findInt == (int)e.Argument) { return true; } else { return false; } }).ToString() + ” by thread with hashcode “ + Thread.CurrentThread.GetHashCode() + “\tto instance ID:\t” + Singleton.Instance.ID.ToString()); } }
We have a program that will count up to 2,000 and use a thread safe singleton to insert and read those 2,000 counters. Each iteration will fire off a new background worker thread to do the work of both the insert and read of each of the iterations counter. Whilst this program serves no useful function, it represents an example of a thread safe singleton where data is shared and accessed in both read and volatile writes concurrently.
Next up
Next up in the series will the prototype pattern and I am going to try and include it with an IronRuby example as well as in C#. The entire Patterns series code and PowerPoint presentation can be downloaded here.
No comments







