Living in the Tech Avalanche Generation

A practitioner’s introspective on technology

Helping Entity Framework v4.0 play it’s <ROLE> – Part 4.0

Before diving in you might like to read parts 1, 2 and 3 if you have come to this post out of sync. Also if you are not familiar with some of the newer aspects of the Code Only CTP for Entity Framework it might be worth looking here on the ADO.Net Team blog.

The Service Layer

nfetchspec_serviceLayer_2

I want to point out that this approach in development is not restricted to a technology or architecture per`se and in discussing how it fits with a ‘Service Layer’ is equally valid for a Layered Request / Response style Architecture and asynchronous messaging systems with very well defined business components.

Let’s start with a run of the mill WCF approach – I have purposely elided the interface contract for the sake of brevity.

[OperationContract(IsOneWay=true)]
[OperationBehaviour(TranactionScopeRequired=true,
                    TransactionScopeAutoComplete=false)]
public void DiscountRunOutProducts()
{
    IList<IRunOutDiscountForProducts> products = null;

    var compParams = new Dictionary<string, string>();
    compParams.Add(_conParamName, _connectionStringOnly);

    var repo = FetchSpec
                    .Configure
                    .With(new IoC())
                    .AndBuildSession<IRunOutDiscountForProducts>(compParams)
                    .ForRepository();

    using (var scope = new TransactionScope(TransactionScopeOption.Required,
        new TransactionOptions()
        {
            IsolationLevel =
                SessionBuilder<IRunOutDiscountForProducts>.ScopeIsolation()
        }))
    {
        products = repo.Get<IRunOutDiscountForProducts>();

        foreach (var product in products)
        {
            product.DiscountProductForRunOut();
        }

        scope.Complete();
    }
}

Every expression of intent here is explicit, from the name of the service operation, all the way to the application of the ROLE to the ORM. From an ongoing maintenance perspective, when any of the given actors need to be varied through the life cycle of the software, this can be done independently. For example, we don’t have to revisit our service layers code when we profile the system and find that the fetching strategy should be eager fetching for a given scenario, instead we can build a new version of the existing Fetching Strategy and drop it in. This kind of flexibility ripples through the system, with the same said for Specifications, Message Handlers, so on and so forth. If of course you wanted to change the code to accept a Specification ‘in line’ rather than have it deployed and dynamically resolved, then you could probably have just implemented an overloaded version of the Service operation to begin with and pass in the parameters required to build those pieces at runtime. The example is a one way operation but you could easily be returning values and accepting parameters (think DTO’s) in a request / response scenario. Bear in mind these DTO’s are not being mapped and subsequently attached, they are either parameters for the ORM or return property buckets for binding or mapping to a presentation model.

For a point of difference, let’s take a look at how this might work if our Service Layer was implemented on top of the popular Open Source Framework NServiceBus.

public class DiscountRunOutProductsMessage: IMessage
{
    public string DiscountedRegion{ get; set; }
    public decimal UnitPrice{ get; set; }
}

public class DiscountRunOutProducts :
             IMessageHandler<DiscountRunOutProductsMessage>
{
    public void Handle(DiscountRunOutProductsMessage message)
    {
        IList<IRunOutDiscountForProducts> products = null;

        var compParams = new Dictionary<string, string>();
        compParams.Add(_conParamName, _connectionStringOnly);

        var repo = FetchSpec.Configure
                            .With(new IoC())
                            .AndBuildSession<IRunOutDiscountForProducts>
                                (compParams)
                            .ForRepository();

        using (var scope = new TransactionScope(TransactionScopeOption.Required,
            new TransactionOptions()
            {
                IsolationLevel =
                    SessionBuilder<IRunOutDiscountForProducts>.ScopeIsolation()
            }))
        {
            var spec = new Specification<IRunOutDiscountForProducts>
                            (p => p.UnitPrice < message.UnitPrice &&
                             p.Supplier.Region = message.DiscountedRegion);

            products = repo.Get<IRunOutDiscountForProducts>(spec);

            foreach (var product in products)
            {
                product.DiscountProductForRunOut();
            }

            scope.Complete();
        }
    }
}

Something worth pointing out in our NServiceBus example is that it too is quite explicit. The message handler, handles messages expressly for the purpose of discounting products to be ‘run out’, exemplifying how the pattern is becoming more entrenched in our style of working. Once again, if we don’t like anything about the way the handler is doing it’s work, we can throw it away in preference for a new implementation.

Not to be left out

Steve left a comment and asked me not to forgo examples that dealt with inserting and updating data, Steve also wanted to know about how I go about dealing with the Unit of Work and the ‘per session’ vs. ‘conversation’ and the differences that spring up and also when working with WCF and dealing with optimistic concurrency. Fortunately this part in the series takes aim squarely at how to go about using Entity Framework in concert with Roles from the Service Layer and we tackle those questions by necessity.

Listing 1.0 – Inserts

public void add_a_product()
{
    var compParams = new Dictionary<string, string>();
    compParams.Add(_conParamName, _connectionStringOnly);

    var repo = FetchSpec.Configure
                        .With(new StubIoc() {
                            ScannedAssemblyPath = _scannedAssemblyPath })
                        .AndBuildSession<ICustomerToAddOrder>(compParams)
                        .ForRepository();

    var spec =
        new Specification<ICustomerToAddOrder>(c => c.CustomerID == “ALFKI”);
    var config = new IQueryConfigurable[] { spec };

    using (var scope = new TransactionScope(TransactionScopeOption.Required,
        new TransactionOptions()
        {
                IsolationLevel =
                    SessionBuilder<ICustomerToAddOrder>.ScopeIsolation()
        }))
    {
        dynamic customer = repo.Get<ICustomerToAddOrder>(config).First();

        var order = repo.IocContainer
                        .ConvertFromRoleToImpl<IOrderToAddToCustomer>();
        order.CustomerID = customer.CustomerID;
        order.Customer = customer;

        customer.AddOrder(order);

        repo.Save();

        scope.Complete();
    }
}

Not entirely in the spirit of things

Notice the use of the dynamic keyword above (suggested by Mark) Let me explain. Due the Entity Frameworks hard and fast rule of only allowing EntityConfiguration<T> to specify a concrete class as it’s generic argument, the flow through effects have rippled out, with the customer variable and the order variable. The problem is that the IoC container can’t know ahead of time what the implementation type for the interface might be and order.Customer property is forced to use a concrete type (not interface) to satisfy the Entity Framework for mapping purposes enforced by EntityConfiguration<T>. After speaking to David DeWinter (a Tester on the EF Team who responded to a tweet I made), he suggested that it was likely implemented this way to satisfy ObjectSet<T> which also constrains to a concrete implementation (makes sense).

Ultimately the dynamic keyword will get us over the line with respect to this one final hurdle, however my gut says that this work around isn’t entirely in the spirit of NFetchSpec and smacks a little of my old enemy the VARIANT, but I’m prepared to make this one allowance to get me working in a way that suits my needs. I can still read the code somewhat clearly because even when I’m using dynamic for assignment, I can reason about the type based on the interface specified to the repository and the IoC container. I would love to think that this is something that the Entity Framework team might address but I guess I will just have to wait and see.

Under the covers

What code did I need to write to support this ‘adding a product to a customer’ scenario? First up I needed the role itself, then the entities, the mapping classes, the mapping role class and I also needed to write an implementation for IProvideIsolationLevelFor. The Specification I chose to write inline because the parameter value would be provided at run time. Here is the all of it:

The Roles

public interface ICustomerToAddOrder
{
    void AddOrder(IOrderToAddToCustomer order);
    string CustomerID { get; set; }
    ICollection<OrderToAddToCustomer> Orders { get; set; }
}
public interface IOrderToAddToCustomer
{
    string CustomerID { get; set; }
    CustomerToAddOrder Customer { get; set; }
    int OrderID { get; set; }
}

The Entities

public class CustomerToAddOrder : IEntity, ICustomerToAddOrder
{
    public string CustomerID { get; set; }
    public ICollection<OrderToAddToCustomer> Orders { get; set; }

    public void AddOrder(IOrderToAddToCustomer order)
    {
        if (Orders == null)
            Orders = new List<OrderToAddToCustomer>();

        Orders.Add(order as OrderToAddToCustomer);
    }
}

public class OrderToAddToCustomer : IEntity, IOrderToAddToCustomer
{
    public string CustomerID
    {
        get;
        set;
    }

    public CustomerToAddOrder Customer
    {
        get;
        set;
    }

    public int OrderID
    {
        get;
        set;
    }
}

The Mapping Classes

public class CustomerToAddOrderMapping : Mapping<CustomerToAddOrder>
{
    public CustomerToAddOrderMapping(string objectSetName)
        : base(objectSetName)
    {
        Property(c => c.CustomerID).HasMaxLength(5).IsRequired();
        HasKey(c => c.CustomerID);
        Relationship(c => c.Orders).IsOptional();
    }
}

public class OrderToAddToCustomerMapping : Mapping<OrderToAddToCustomer>
{
    public OrderToAddToCustomerMapping(string objectSetName)
        : base(objectSetName)
    {
        Property(o => o.OrderID).IsIdentity();
        Property(o => o.CustomerID).HasMaxLength(5).IsRequired();
        HasKey(o => o.OrderID);
        Relationship(o => o.Customer)
            .FromProperty(c => c.Orders)
            .HasConstraint((o, c) => o.CustomerID == c.CustomerID);
    }
}

The Mapping Role

public class CustomerToAddOrderMappingRole :
        IMappingRole<ICustomerToAddOrder>
{
    private IMapping[] _mappings;

    public CustomerToAddOrderMappingRole()
    {
        _mappings = new IMapping[]
        {
            new CustomerToAddOrderMapping(“Customers”),
            new OrderToAddToCustomerMapping(“Orders”)
        };
    }

    public IMapping[] Mappings
    {
        get { return _mappings; }
    }
}

The Transaction Isolation Class

public class AddOrderToCustomerIsolation :
        IProvideIsolationLevelFor<ICustomerToAddOrder>
{
    public IsolationLevel GetScopeIsolationForRole
    {
        get { return IsolationLevel.ReadCommitted; }
    }
}

Piggy in the middle

The issue of managing a short or extended session with an ObjectContext is something that I think a lot of people struggle with. Personally I have never had such an issue because they way I have always worked always involved fetching the most current version of the data I required to have my domain model work against it. This way of working has stayed with me through time immemorial, even in my dark old days of using an anaemic domain model.  To be clear I do not pass DTO’s around and reattach them to the ObjectContext, rather refreshing the data and letting the domain model’s business logic take care of the rest.

In Conclusion

My initial planning for the series was that would be take up four posts and therefore it is expected that this may be the last in the series. However, given that Entity Framework 4.0 is still not at RTM and Code Only is still in CTP then it’s possible I may revisit it with a further post sometime in the future.

Share/Save/Bookmark

2 comments

SOA and Messages - What’s in a name

So the question is what’s in a name, when it comes to considering messages of the SOA variety, or to be more precise in a messaging system? Well I guess it depends on who you ask doesn’t it and let’s for argument sake extend the idea of the ‘who’ to include the implementing technologies of the day and any of their accompanying GBE (guidance by example). Consider this fragment of WCF code that declares the signature of a service. The example comes from the MSDN stock trader example application.

Listing 1.0

[ServiceContract(Name = "OrderProcessorService",
    Namespace = "http://Trade.TraderOrderHost")]
public interface IOrderProcessor
{
    [OperationContract(Action = "SubmitOrderTransactedQueue",
        IsOneWay = true)]
    void SubmitOrderTransactedQueue(OrderDataModel order);

    [OperationContract(Action = "SubmitOrder",
        IsOneWay = true)]
    void SubmitOrder(OrderDataModel order);
}

Self Evident?

The first thing I would like to highlight about this example is the name of the service itself, it has a very generic sounding name that does not say a lot about the domain in which we are processing orders. True enough there is some clue in the WCF ServiceContract attribute property assignments but is that sufficient? The next thing I want to point out is that when an order is submitted with the intent that it should be stored in a transactional queue, the service operation responsible has been named specifically to speak to that intent (of storing in a queue). The fact that the message is stored in a queue is an implementation detail and on the surface it appears  has absolutely no association to the business context of the operation, which is to “submit an order”. If on the other hand there is a business requirement to have *certain* messages stored in a durable transactional queue, we should probably be taking those business considerations into account with respect to naming the message handler (operation). Making some assumptions, perhaps this would a better naming scheme for that scenario:

Listing 2.0

[OperationContract(Action = "SubmitStrategicCustomerOrder", IsOneWay = true)]
void SubmitStrategicCustomerOrder(OrderDataModel order);

Next up lets focus on the name of the operations single argument OrderDataModel, which is significant for a couple of reasons. Firstly, is this operator really a model – its name says it is? Certainly not if we want to hold it up to the DDD definition, it carries no behaviour with it – it’s just data, information about the order that is being “submitted”. So is OrderDataModel a DTO? If feels like a DTO doesn’t it, thus we should ask what is the message? I am not going to get too heavily into a discussion of what constitutes the ‘message’ when it comes to SOAP services, only to reflect that many consider it to be the combination of the operations and their operators, whilst some consider it to be just the operators alone and others don’t speak of messages at all and consider an operations arguments as nothing more than DTO’s.

Let’s take a different approach to this problem, what if we were to name the contract for this service IProcessOrders and include handlers (methods) for cancelling the order amongst other things.

Listing 3.0

public class StockTradeOrderService : IProcessStockTradeOrders
{
    public void Submit(OrderMessage order)
    {
        //….etc
    }

    public void Cancel(OrderMessage order)
    {
        //….etc
    }
}

I cant say it feels right to me yet but gradually I do feel as though the names of this service and the intent expressed by it’s message handlers are becoming somewhat more reflective of the business problem it attempting to solve, making the code easier to reason about.

Lets have a look at how I might go about specifying the contract and implementation for such a service using NServiceBus.

Listing 4.0

public class SubmitOrderMessageHandler : IMessageHandler<SubmitOrderMessage>
{
    public IBus Bus { get; set; }

    public void Handle(SubmitOrderMessage message)
    {
        OrderSubmittedResponseMessage response =
            new OrderSubmittedResponseMessage ();

        //more processing to act on the order message

        this.Bus.Reply(response);
    }
}

What about cancelling the order then?

Listing 5.0

public class CancelOrderMessageHandler : IMessageHandler<CancelOrderMessage>
{
    public IBus Bus { get; set; }

    public void Handle(CancelOrderMessage)
    {
        //processing
    }
}

Structural differences aside, I still feel strange about the whole SubmitOrder aspect to the naming as it stands, it still feels a tad too generic for my liking. To be fair, an order service might not be something that would be modelled with singular discrete message handlers like this, perhaps it would better be modelled as a Saga (think persisted workflow), just as it is in the NServiceBus samples, but that’s not the focus here so we wont dwell on that either.

The SubmitOrderMessageHandler demonstrated above, handles messages of the type SubmitOrderMessage, where the IMessageHandler provides us (via the strategy pattern) a Handle<T> method, where T is the message type and the Handle methods body has the express purpose of implementing the logic for handling the message.

image By now you can probably see where this all going? The “data” contained in the SubmitOrderMessage is certainly different to the data contained in the CancelOrderMessage and if we shift our focus now back to the WCF stock trader example to consider the OrderDataModel (the argument to the SubmitOrder method) then its evident that the message carries some data used by the generic handler to examine more closely exactly what the intent is (beyond the ‘submission’ of the order). Again this is not plainly clear from the name of the message alone. The OrderDataModel data contract has a property (of string) called ‘orderType’ and looking at the component that has the responsibility of processing orders, we can see that it checks the value of the ‘orderType’ to discern whether or not to process the order to BUY or SELL.

Listing 6.0

if (order.orderType == StockTraderUtility.ORDER_TYPE_BUY)
{
    //…do some work for a buy order
}
else if (order.orderType == StockTraderUtility.ORDER_TYPE_SELL)
{
    //…do some work for a sell order
}
So up to this point we still don’t really have a good naming approach tied down, it’s clear that the intent to ‘BUY’ or ‘SELL’ is not represented in the name of the message at all. However what if the contents of a ‘BUY’ and ‘SELL’ message are semantically equivalent? Is that kind of generality enough to encourage us to become more lax and collapse these very different types of business events into one single message? Personally I don’t believe so. Let’s put on our versioning hat for just a minute and try and imagine what will start to happen when requirements for the system reveal cases that  require new fields (data). For example, a ‘BUY’ order message requires a new field and suddenly we have lost our semantic equivalence and our message starts to exhibit some of the frailty it posses by attempting to be so generic. It’s therefore important to put a solid abstraction on the message contract so that with variation over time the system doesn’t suffer under the weight of brittle message contract design.
image This small snippet of decisional code in listing 6.0 underlines how the naming of the Service Contract and Data Contracts in the example do not really make a good job in delivering code that is self describing from a business context and is therefore harder to read and reason about it. In the NServiceBus example however it’s plainly evident what to expect from each message and its handler. I should point out that it is possible to borrow the style encouraged in NServiceBus and implement it in WCF (to some degree); once such approach is using un-typed messages where the body of the message contains a serialised message <T> and Services receiving messages of type <T> can have registered message handlers that can be matched to deserialized messages of <T>, finally having their Handled method called. I covered this somewhat in another post.

Generic in the name of Reuse?

imageIn an article by Thomas Erl, he speaks of more ‘generic’ naming schemes when it comes to ‘utility services’ but I don’t have any genericbusiness’ operations because the domain in which I work is not typically generic. Therefore when I put on my AOP hat and start thinking about some of the cross cutting concerns that crop up in any number of business domains, such as the ubiquitous logging for example, shouldn’t I reasonably be expected to relax my naming sensibility? But that’s not really the problem under discussion here is it.

Lets take the code now from listing’s 4.0 and 5.0 and propose a new approach to the model suggested by the Stock Trader for the submission of buying and selling trades:

public class SubmitBuyOrderMessageHandler : IMessageHandler<BuyOrderMessage>
{
    public IBus Bus { get; set; }

    public void Handle(BuyOrderMessage)
    {
        BuyOrderResponseMessage response =
            new BuyOrderResponseMessage ();

        //more processing to act on the order message

        this.Bus.Reply(response);
    }
}

public class SubmitSellOrderMessageHandler : IMessageHandler<SellOrderMessage>
{
    public IBus Bus { get; set; }

    public void Handle(SellOrderMessage)
    {
        SellOrderResponseMessage response =
            new SellOrderResponseMessage();

        //more processing to act on the order message

        this.Bus.Reply(response);
    }
}

Messages and their names should map closely to business events modelled by the system; business events as such should have their names represented in non generic terms with more focus on their explicit context. I want to build self evident, self describing business systems where things like implementation details should certainly not figure in the naming of messages or their handlers, that’s something for ‘other’ documentation.

Share/Save/Bookmark

1 comment

If I had a Fluent Interface for WCF Configuration I would…..

It would look something like this I guess:

var config = Wcf.Configure
                .AddressAt(“net.tcp://localhost:9002/myservice”)
                .TransportOn(Transports.Tcp)
                .SecureFor(SecurityMode.None)
                .etc
                .etc

I think this gets idea over? I have at least one volunteer (bravo Mark) and so Hi Ho Hi Ho it’s off to work we go.

Share/Save/Bookmark

6 comments

Next Page »

Creative Commons Attribution-ShareAlike 2.5 Australia
Creative Commons Attribution-ShareAlike 2.5 Australia