Archive for the 'LINQ' Category
Doing .NET Days – Latest
The inaugural “doing .NET days” is filling up fast but there are a few spots left. If you are interested in learning more about LINQ and it’s different flavours and getting an introductory look at nServiceBus (a mighty powerful Framework for Distributed Systems development), then please grab one of the few remaining spots before they disappear.
You can find more details about the event here and here.
No commentsAnnouncing “Doing .NET Days” – Day 1 (.NET Training)
Something that has been on my mind for some time now has been an urge to do
some local community work through my council community centre and “Doing .NET Days” is the expression of that urge. What is “Doing .NET Days”? The idea is that once a month I will be offering free (gold coin donation) whirlwind introductory level training on a variety of subjects, approximately three subjects per .NET Day!
The venue for “Doing .NET Days” will be static for the time being and the event be conducted at the Point Cook Community Centre in Point Cook Melbourne Australia. The number of seats for the event is limited (size of the room) and for the moment it caters to 10 seats (each with a PC supplied) so if you want to be involved you will need to be in the first 10 to register. if you want to be introduced to something new that you might not have had the time to check out till now.
Doing .NET Days – Day #1 Agenda
To kick things off were going to take a look at the following:
- An introductory look at messaging with NServiceBus.
- An introductory look at LINQ and it’s flavour of providers (LINQ To Objects, XML, SQL and Entity Framework)
To start off with I am holding 5 seats for graduates yet to find their first developer role in the workforce. I remember what it’s like trying to break in and get that first gig and I would have appreciated the help back then! If the graduate positions are not taken up within the next two weeks, I will open those seats up as well. Here are the rest of the event details:
- Saturday 22th August 2009
- Location – Point Community Centre
- 10:00 AM – 4:00PM
- Lunch is BYO or there are a number of cafes and restaurants in the town centre.
- To register email me your details and I will contact you with further details.
I will post a comment on this post every time a position is taken up so people can tell how many positions remain open.
12 commentsEntity Framework, Fluent Interfaces & Domain Specific Languages Part 2
In the first part of this series I looked at how you might go about building an (incredibly tiny) domain specific language for analysing data. The context I gave was a scenario where project managers were required to work with a continuous stream of data in the form of a known schema. This ‘known’ schema is most commonly used in moving and transforming data between various systems in a domain where the central or end target is a Document Management System. The ‘known’ schema is an agreed format that all systems in this particular industry use to extract and subsequently load. It is common to see the project managers struggling with tools like access to compose queries to analyse the data before or after these ETL processes and hence proposition of a DSL.
In the first part I wasn’t particularly happy with the underlying behaviour of the language statements; we were producing a cascading set of queries, rather than composing a query structure. This time around we look to achieve this compositional affect with a fluent interface that issues a beginning statement and subsequently composes a query until a finalizing command is submitted to indicate that execution should take place against the database. If we use Specifications to compose the predicates in querying the database we can achieve the composition through chaining extension methods and thus build up an execution context from the syntax in our language.
Consider this fluent interface:
public void prints_order_lines_grouped_by_customer_and_orders() { NorthwindLangQuery .BeginQuery() .Customers() .With_An_Id_Equal_To(“ALFKI”) .With_Orders_Shipped_From(“Germany”) .That() .Are() .Older_In_Years_By(2) .EndCustomerQuery() .Print_Customer_Orders_To_Console_Window(); }
Instead of cascading sub queries that work on an initial database query as with the code shown in part 1, we use the specification pattern to build up predicates that we submit with a single SQL (LINQ To Entities) query to the database. If we pull apart the NorthwindLang query above and follow it method by method here is what it looks like:
public static NorthwindLang BeginQuery() { _customerSpec = new Specification<Customer>(c => c == c); _orderSpec = new Specification<Order>(o => o == o); _orderLineSpec = new Specification<OrderLine>(ol => ol == ol); return new NorthwindLang(); }
The BeginQuery() method simply primes each of our specifications which progressively are built upon in the following chained method calls.
No change required in the method body below as we already know we are dealing with a customer.
public static Specification<Customer> Customers(this NorthwindLang query) { return _customerSpec; }
Next the specification has a filtering expression to the customer ID appended using the logical AND operator.
public static Specification<Customer> With_An_Id_Equal_To (this Specification<Customer> customers, string id) { var cust_id_spec = new Specification<Customer>(c => c.CustomerID == id); _customerSpec &= cust_id_spec; return _customerSpec; }
The customer orders are also required in the query so we are going to need to setup the Orders specification with it’s required predicate.
public static Specification<Order> With_Orders_Shipped_From (this Specification<Customer> customers, string country) { Specification<Order> order_shipcountry_spec = new Specification<Order>(o => o.ShipCountry == country); _orderSpec &= order_shipcountry_spec; return _orderSpec; }
The next two parts of the query are benign and have no effect on the composition of the query and only play a part in providing a more natural syntax composition for the language.
public static Specification<Order> That (this Specification<Order> orders) { return _orderSpec; } public static Specification<Order> Are (this Specification<Order> orders) { return _orderSpec; }
Next we add a further Orders specification limiting the result set to orders more than twelve years old.
public static Specification<Order> Older_In_Years_By (this Specification<Order> orders, int age) { var date = DateTime.Now.AddYears(-age); Specification<Order> order_older_spec = new Specification<Order>(o => o.OrderDate < date); return _orderSpec &= order_older_spec; }
Finally we demarcate the end of the query by calling one of the finalization methods that can only be followed by subsequent printing methods.
public static IEnumerable<LangDomain.Customer> EndCustomerQuery(this Specification<Order> orders) { return DomainQuery<LangDomain.Customer> .CreateQuery(_customerSpec, _orderSpec); }
This is still all proof of concept stuff and I plan to follow up with putting a harness together with the Fireball code editor API. Here is a further list of some of the other language statements that the fluent interface is capable of producing at the time of this writing.
public void prints_order_lines_grouped_by_customer_and_orders() { NorthwindLangQuery .BeginQuery() .Customers() .With_An_Id_Equal_To(“ALFKI”) .With_Orders_Shipped_From(“Germany”) .That() .Are() .Older_In_Years_By(2) .EndCustomerQuery() .Print_Customer_Orders_To_Console_Window(); } public void selects_customers_by_id() { var cust = NorthwindLangQuery .BeginQuery() .Customers() .With_An_Id_Equal_To(“ALFKI”) .EndCustomerQuery() .As_Unique_Where_Customers_Ids_Are_The_Same(); foreach (var c in cust) { Console.WriteLine(c.CompanyName); } } public void selects_orders_specified_by_age_of_orders_with_ specified_freight_costs() { var query = NorthwindLangQuery .BeginQuery() .Orders() .Older_In_Years_By(12) .With() .Freight_Costs_More_Than(360) .EndOrderQuery(); foreach (var o in query) { foreach (var ol in o.Order_Details) { Console.WriteLine(o.OrderID + ” : “ + o.Freight + ” : “ + ol.ProductID); } } } public void selects_customers_by_id_for_advanced_users() { var cust = NorthwindLangQuery .BeginQuery() .Customers() .EndCustomerQuery() .As_Unique_Where((cLeft, cRight) => cLeft.CustomerID == cRight.CustomerID); foreach (var c in cust) { Console.WriteLine(c.CompanyName); } }
You can download the entire source code from the repository here.
No comments







