Archive

Archive for June, 2009

Entity Framework, Fluent Interfaces & Domain Specific Languages Part 2

June 17th, 2009 Simon Segal No comments

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();
}
which produces the following output:
Order ID: ALFKI
10643
Product ID 28 x 15 units @ total cost = 683.8500
Product ID 39 x 21 units @ total cost = 377.8500
Product ID 46 x 2 units @ total cost = 23.8500
10692
Product ID 63 x 20 units @ total cost = 877.8500
10702
Product ID 3 x 6 units @ total cost = 59.8500
Product ID 76 x 15 units @ total cost = 269.8500
10835
Product ID 59 x 15 units @ total cost = 824.8500
Product ID 77 x 2 units @ total cost = 25.8500
10952
Product ID 6 x 16 units @ total cost = 399.8500
Product ID 28 x 2 units @ total cost = 91.0500
11011
Product ID 58 x 40 units @ total cost = 529.8500

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.

Share/Save/Bookmark

Type Member Name Resolution with Functions – Part 2.0

June 16th, 2009 Simon Segal 1 comment

Adding to the previous post, the PropertyNameResolver class needs to expand it’s horizons and resolve method names and field names. Given the expanded requirement we probably need to refactor the name of the class to something more appropriate. Here is a more fleshed out idea of what it might look like:

public class MemberNameResolver<T>
{
    public static string ResolveProperty<TPropertyType>
        (Expression<Func<T, TPropertyType>> expression)
    {
        Func<Expression<Func<T, TPropertyType>>, string>
            prop_name_function = l =>
        {
            return GetNameFromExpression(l.Body);
        };
        var property_name =
            typeof(T).GetProperty(prop_name_function(expression)).Name;
        return property_name;
    }

    public static string ResolveMethod(Expression<Action<T>> expression)
    {
        Func<Expression<Action<T>>, string>
            prop_name_function = l =>
            {
                return GetNameFromExpression(l.Body);
            };
        var property_name =
            typeof(T).GetMethod(prop_name_function(expression)).Name;
        return property_name;
    }

    public static string ResolveField<TPropertyType>
        (Expression<Func<T, TPropertyType>> expression)
    {
        Func<Expression<Func<T, TPropertyType>>, string>
            prop_name_function = l =>
            {
                return GetNameFromExpression(l.Body);
            };
        var property_name =
            typeof(T).GetField(prop_name_function(expression)).Name;
        return property_name;
    }

    private static string GetNameFromExpression(Expression body)
    {
        if (ExpressionType.MemberAccess == body.NodeType)
        {
            var memberExpr = (MemberExpression)body;
            return memberExpr.Member.Name;
        }
        else if (ExpressionType.Call == body.NodeType)
        {
            var methodExpr = (MethodCallExpression)body;
            return methodExpr.Method.Name;
        }
        else
        {
            throw new NotImplementedException(
                string.Format(“Resolving names from expression types “ +
                “of {0} is not implemented!”,
                body.Type.Name));
        }
    }
}
Previously we did not account for method calls and as one kind soul articulately pointed out, the string manipulation was somewhat awkward. Mark pointed out Damien’s neat solution by way of digging into the expression body.

Notice the newly specialized Resolve methods now allow a usage like the following:

var member1 =
    MemberNameResolver<Criteria>
    .ResolveProperty<int>(c => c.PageCounter);
var member2 =
    MemberNameResolver<Criteria>
    .ResolveMethod(c => c.SomeMethod());
var member3 =
    MemberNameResolver<Criteria>
    .ResolveField(c => c.Percent);
var member4 =
    MemberNameResolver<Criteria>
    .ResolveMethod(c => c.SomeMethodWithArgs(default(string),
        default(int), default(string[])));

Console.WriteLine(member1);
Console.WriteLine(member2);
Console.WriteLine(member3);
Console.WriteLine(member4);

Producing the following output:

console_functions_memer_resolve1

Getting more out of Functions

So far the approach is a little static from a functional point of view so perhaps we could do this a little differently? If we define the following functions we get some equivalent behaviour to our utility class.

Func<Expression<Func<Criteria, int>>, Expression> criteriaFunction =
    c => c.Body;

Func<Expression, string> propertyResolverFunction = e =>
{
    if (ExpressionType.MemberAccess == e.NodeType)
    {
        var memberExpr = (MemberExpression)e;
        return memberExpr.Member.Name;
    }
    else if (ExpressionType.Call == e.NodeType)
    {
        var methodExpr = (MethodCallExpression)e;
        return methodExpr.Method.Name;
    }
    else
    {
        throw new NotImplementedException(
            string.Format(“Resolving names from expression types “ +
            “of {0} is not implemented!”,
            e.Type.Name));
    }
};

var propertyName =
    propertyResolverFunction(
        criteriaFunction(c => c.PageCounter));

Console.WriteLine(propertyName);

Here we have created two functions that can be used together to achieve our required end result. The first function criteriaFunction, takes a generic expression as an argument and returns an expression. The second function propertyResolverFunction, takes an expression as it’s argument and returns a string. By passing one function as an argument to the other, we achieve the same results as with the static utility class already demonstrated. To collapse this even further we can wrap up both those functions  into one.

Func<Expression<Func<Criteria, string>>, Func<Expression, string>> allInOne =
    c => e =>
    {

        if (ExpressionType.MemberAccess == e.NodeType)
        {
            var memberExpr = (MemberExpression)e;
            return memberExpr.Member.Name;
        }
        else if (ExpressionType.Call == e.NodeType)
        {
            var methodExpr = (MethodCallExpression)e;
            return methodExpr.Method.Name;
        }
        else
        {
            throw new NotImplementedException(
                string.Format(“Resolving names from expression types “ +
            “of {0} is not implemented!”,
                e.Type.Name));
        }
    };

Expression<Func<Criteria, string>> exp = c => c.Levels;
var property_name_allinone = allInOne(exp)(exp.Body);

Console.WriteLine(property_name_allinone);

When we call the allinone function with the expression argument, it returns a function that in turns take the body property of the same expression that was passed to the higher order function. All the code in the post presumes the the following class:

public class Criteria
{
    public decimal Percent;

    private int _pageCounter;

    public int PageCounter
    {
        get { return _pageCounter; }
        set { _pageCounter = value; }
    }

    private string _levels;

    public string Levels
    {
        get { return _levels; }
        set { _levels = value; }
    }

    public void SomeMethod() { }

    public void SomeMethodWithArgs(string arg1, int arg2,
        params string[] arg3) { }
}

Share/Save/Bookmark

Categories: C#, LINQ Tags: ,

Ten+ Year Perspective

June 13th, 2009 Simon Segal 1 comment

This blog is normally strictly technical and I will rarely deviate from that self imposed constraint but in a rare deviation here goes with something a bit different.

For anyone who just happened upon this post and perhaps those who know me or have followed this blog may or may not be aware, I was a musician in one of my previous careers. I have not abandoned my music completely in the decade or so that I moved into software however let’s just say it took a very big back seat.

Initially drawn to software development as a better paying yet still highly creative profession, I would often tell myself that writing good code was like writing or producing a good song and though the output was different in format and audience expectations, the experience was still fulfilling a side of me that required feeding.

A decade into my software development career and I can now say that whilst it does satisfy a creative urge, it can never come close to the emotional connection and responses that music emote in me. Recent days spent with headphones and my MP3 player have me on the verge of propelling myself into some musical journey and exactly what that is I am not sure right now but I am filled with excitement and overwhelming sense of promise.

My final observation is this: even with a strong resolve to travel some undiscovered musical road, I still feel the ‘coding’ drug flowing through my veins. I am, I code, I live, I die.

Share/Save/Bookmark

Categories: Career Tags:
Creative Commons Attribution-ShareAlike 2.5 Australia
Creative Commons Attribution-ShareAlike 2.5 Australia