Archive for April, 2009
Scaling Out of the Box ERP and CRM whilst you get some REST.
Many ERP / CRM products are coming to market spouting Web Services as their customisation and integration saviour. These products are exposing their innards to the world via a SOAP Web Service layers, a design which is often tightly coupled to their more familiar units of extensibility or API’s. What does that mean? As an example, NAV 2009 will allow you to expose known development artefacts such as ‘Pages’, ‘Code Units’ etc as SOAP Endpoints (Web Services) and the Sage Accpac products also encourages integration via a web service layer.
So, Integration…..yes I guess so….. and custom solutions interfacing with a given system, well yes a bit of that too, but scalable, that I am not too sure about. One way of making such systems more scalable is to introduce a bit of publish and subscribe, some good old HTTP and a little resource
oriented Architecture. By simply monitoring events in the system and by publishing those events and their data we can do interesting things.
Building Around the Edges
It’s a popular approach to customise an alternative User Interface for OOTB ERP systems. There are many simple things you can do to make your custom system more scalable - for instance, when fetching semi static data you might think about publishing it as a HTTP resources and putting REST to work, the net effect of which should greatly reduce the all too common syndrome we have observed in systems that make constant and arguably redundant request / response calls to the systems API and consequently over working it’s database system. This approach was detailed very elegantly a while back by Udi.
As percentage, the number of request messages (request / response) made when there has been little or no change to semi static data is often alarmingly high. Nonetheless, it is commonplace to see applications employ this ‘ask and wait’ routine, which places a cascade of over utilisation across all the systems involved in the call chain. By publishing semi static data when events occur you can save precious resources and gain significant scale.
Udi recently reminded me that NServiceBus provides another way of approaching this problem and of course as usual he’s right. If developers can get their heads around PUB / SUB and the fundamental shift in approach it requires without getting sidetracked by everything that they have done in the past, then this can be a very satisfying way of working. The outcome is that we can build a system that customises user experience with OOTB CRM or ERP systems, without placing the same kind of request / response stresses that we would usually create if we choose to use the vendors Web Service option.
No commentsEntity Framework Profiler hosts IronRuby and IronPython
I mentioned recently that I wanted to add IronRuby scripting into the profiler so users could compose scripts and execute Entity Framework code directly from the Profiler itself. After looking around at how to host IronRuby in my own application it became clear very quickly that I was about to set out on building something quite redundantly. IronEditor, DLRPAD to name a few, offer this functionality, so all I needed was to grab one such tool whose license and functionality were a match. I decided on IronEditor. IronEditor is a Windows Forms application that embeds a IronRuby console and allows both IronRuby and IronPython scripting, so immediately I gained a benefit of adding support to both languages.
Unfortunately IronEditor has a lot of the required code embedded in a Windows Form causing me to rework the source a little to turn the Form in to a User Control which I can easily host in the profiler using the WPF Windows Forms Host. This will also require some reworking of the WCF code, as the client and server will be in the same application and to be frank WCF is overkill and I am going to refactor the messaging with sockets more than likely. It’s not quite ready but here’s a screen shot of what to expect.
Exhibit 1.0
Exhibit 1.0 demonstrates the an IronRuby script that works against one of my C# Entity Framework Repository libraries.
Exhibit 2.0
Exhibit 2.0 displays the TSQL that is run as result of the one of the queries that are run by the IronRuby script.
Exhibit 3.0
Exhibit 3.0 shows the Meta Data View also produced by running the same IronRuby script.
The IronRuby Script
require ‘System.Windows.Forms, Version=2.0.0.0, ‘ + ‘Culture=neutral, PublicKeyToken=b77a5c561934e089′ require ‘D:/simon.segal/Local Working/Org.TechA.EF.Profiler’ + ‘/Org.TechA.EF.Profiler.Tests/bin/Debug’ + ‘/Org.TechA.EF.Profiler.Tests.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′ $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://*/NorthWindModel.csdl|res://*/” + “NorthWindModel.ssdl|res://*/NorthWindModel.msl” #get the connection string $con = $entityBuilder.ToString() puts $con #set up the ObjectContext $session = Org::TechA::EF::Profiler::Tests::NorthwindEntities.new($con) #Get all the customers $custs = $session.Customers $custs.each {|cust| puts cust.CompanyName} #Get all the orders $orders = $session.Orders $orders.each {|order| puts order.OrderID}
So more than just pictures?
I expect to have a working revision out within a week or so but the current version without the scripting ability is still available here.
1 commentLINQ To XML and the Specification Pattern - [In a static world]
I have documented quite extensively on how to use the Specification Pattern and in particular how that can work with a variety of LINQ flavours. The pattern has proven useful in matching objects based on a computation that seeks to test equality and when turned slightly on it’s head a little, it can provide dynamic querying capability to the current Microsoft group of ORM products, namely LINQ To SQL and the Entity Framework. You can check out most of the series on this topic from here. In more recent times I looked at how to use the same pattern with IronRuby which whilst very satisfying for the author, it currently lacks the ability to produce expressions that either ORM products are capable of utilising.
So, for the moment I want to go back again to the Specification pattern and explore it’s use specifically in the world of C# and it’s statically typed sibling languages. The Specification that I currently use is based primarily around our ability to push around Expression<Func<T>> and Func<T> as delegates that can be used as arguments to the extension methods in a given LINQ implementation. Therefore, LINQ to XML should be no exception. Given that the class at the centre of all this ( Specification<T> ) matches objects that satisfy a boolean condition that is asserted using the generic T argument, we are able to specify a function to pass to any extension method implemented by the LINQ To XML provider, that takes a generic as it’s input parameter and returns a boolean. A quick reminder of the Specification classes interface:
public interface ISpecification<T> { Expression<Func<T, bool>> EvalPredicate { get; } Func<T, bool> EvalFunc { get; } bool Matches(T entity); }
Here is a simple example of filtering a query over XML data by supplying a predicate in the form of a specification.
public void employees_from_uk() { var all_employees_on_file = XDocument.Load(@"..\..\XML\Employees.xml").Descendants(); Specification<XElement> aus_emp_spec = new Specification<XElement> (x => x.Attribute("Country").Value == "Australia"); var aus_employees = from e in all_employees_on_file.Descendants() .Where(aus_emp_spec.EvalFunc) select e; aus_employees.ToList().ForEach(x => { Console.WriteLine(x.ToString()); }); }
And now a more complex specification that uses the AND operator to create a combined set of conditions to be satisfied in a .Where extension method.
public void employees_from_uk_that_are_ceo() { var all_employees_on_file = XDocument.Load(@"..\..\XML\Employees.xml").Descendants(); var aus_emp_spec = new Specification<XElement> (x => x.Attribute("Country").Value == "UK"); var ceo_emp_spec = new Specification<XElement> (x => x.Attribute("Title").Value == "CEO"); var compound_spec = aus_emp_spec & ceo_emp_spec; var aus_employees = from e in all_employees_on_file.Descendants() .Where(compound_spec.EvalFunc) select e; aus_employees.ToList().ForEach(x => { Console.WriteLine(x.ToString()); }); }
More than just a ‘Where’ predicate?
Your probably noticing that we are always applying our specifications to the “where” method. As I mentioned, a Specification in it’s current incarnation can only be applied to extension methods that take a function that accepts a generic argument as an input parameter and returns a boolean, therefore there are some other methods that can be specified. Here is example of using the .SkipWhile() extension method.
public void skip_while_employees_from_usa_then_return_the_rest_regardless() { var all_employees_on_file = XDocument.Load(@"..\..\XML\Employees.xml").Descendants(); var usa_empoyee_spec = new Specification<XElement> (x => x.Attribute("Country").Value == "USA"); var usa_emps = from e in all_employees_on_file.Descendants() .SkipWhile(usa_empoyee_spec.EvalFunc) select e; usa_emps.ToList().ForEach(x => { Console.WriteLine("Skipping from the USA : " + x.ToString()); }); }
The final example combines data from two XML sources, each one requiring it’s own specification, where the LINQ query will bring the disparate data together.
public void customer_joined_with_customer_representative() { var cust_rep_spec = new Specification<XElement>(x => x.Name == "CustomerRep"); var emp_id_spec = new Specification<XAttribute>(x => x.Name == "EmployeeID"); var all_employees_on_file = XDocument.Load(@"..\..\XML\Employees.xml").Descendants().Attributes(); var all_customers_on_file = XDocument.Load(@"..\..\XML\Customers.xml").Root.Descendants().Elements(); var customer_with_rep = from c in all_customers_on_file.Where(cust_rep_spec.EvalFunc) from e in all_employees_on_file.Where(emp_id_spec.EvalFunc) where c.Value == e.Value select new { c = c.Parent.Element("FirstName").Value + " " + c.Parent.Element("LastName").Value, e = e.Value }; customer_with_rep.ToList().ForEach(x => { Console.WriteLine( string.Format("Customer : {0} is represented by Rep Number {1}", x.c, x.e)); }); }
Employee.xml File
<?xml version="1.0" encoding="utf-8" ?> <Employees> <Employee EmployeeID="1" FirstName="Nancy" LastName="Davolio" Title="Sales Representative" HireDate="1992-05-01T00:00:00" Country="USA" Extension="5467" /> <Employee EmployeeID="2" FirstName="Andrew" LastName="Fuller" Title="Vice President, Sales" HireDate="1992-08-14T00:00:00" Country="AUSTRALIA" Extension="3457" /> <Employee EmployeeID="3" FirstName="Janet" LastName="Leverling" Title="Sales Representative" HireDate="1992-04-01T00:00:00" Country="USA" Extension="3355" /> <Employee EmployeeID="4" FirstName="Margaret" LastName="Peacock" Title="Sales Representative" HireDate="1993-05-03T00:00:00" Country="AUSTRALIA" Extension="5176" /> <Employee EmployeeID="5" FirstName="Steven" LastName="Buchanan" Title="Sales Manager" HireDate="1993-10-17T00:00:00" Country="UK" Extension="3453" /> <Employee EmployeeID="6" FirstName="Michael" LastName="Suyama" Title="Sales Representative" HireDate="1993-10-17T00:00:00" Country="UK" Extension="428" /> <Employee EmployeeID="7" FirstName="Robert" LastName="King" Title="CEO" HireDate="1994-01-02T00:00:00" Country="UK" Extension="465" /> <Employee EmployeeID="8" FirstName="Laura" LastName="Callahan" Title="Inside Sales Coordinator" HireDate="1994-03-05T00:00:00" Country="USA" Extension="2344" /> <Employee EmployeeID="9" FirstName="Anne" LastName="Dodsworth" Title="Sales Representative" HireDate="1994-11-15T00:00:00" Country="UK" Extension="452" /> </Employees>
Customers.xml File
<?xml version="1.0" encoding="utf-8" ?> <Customers> <Customer> <FirstName>Simon</FirstName> <LastName>Segal</LastName> <JoinDate>19-10-2008</JoinDate> <Country>Australia</Country> <Email>simon.segal@techavalanche.com</Email> <MobilePhone>0405987367</MobilePhone> <CustomerRep>2</CustomerRep> </Customer> <Customer> <FirstName>Bob</FirstName> <LastName>Jones</LastName> <JoinDate>23-10-2008</JoinDate> <Country>Germany</Country> <Email>bob.j@bundes.com</Email> <MobilePhone>8983478347</MobilePhone> <CustomerRep>1</CustomerRep> </Customer> <Customer> <FirstName>Clair</FirstName> <LastName>Humgola</LastName> <JoinDate>10-10-2008</JoinDate> <Country>Australia</Country> <Email>chumg@telstra.com.au</Email> <MobilePhone>0458193487</MobilePhone> <CustomerRep>4</CustomerRep> </Customer> <Customer> <FirstName>Milton</FirstName> <LastName>Nomik</LastName> <JoinDate>20-12-2008</JoinDate> <Country>Australia</Country> <Email>milt.n@techavalanche.com</Email> <MobilePhone>09072625717</MobilePhone> <CustomerRep>6</CustomerRep> </Customer> </Customers>
On a final note: I am going to have a go shortly at putting together some variations of the Specification<T> class to allow for a more complete use with LINQ in General, remembering that the initial requirement was based around testing objects for equality and then creating a more manageable and malleable system of creating dynamic queries in LINQ To SQL and the Entity Framework. The “new” Specification class will need to support more than the just Func<T, bool> and should prove to be in interesting exercise.
Full code download for this post can be found here.
No comments







