Living in the Tech Avalanche Generation

A practitioner’s introspective on technology

Archive for July, 2009

Entity Framework 4.0 and Fetching Strategies

I have spent a fair amount of time already trying to improve my experience with the Entity Framework with versions 1.0, 2.0 and 3.0. Well that’s a bit of joke really because there was and never will be versions 2.0 or 3.0 for the Entity Framework with the decision to take the next version straight to Version 4.0 to align with the .Net Framework Version. Nonetheless I have previously spent quite a bit of time working at being more explicit with how to fetch data with the Entity Framework.

Fetching Strategies are a key concept when considering tuning your data access code in Event Driven Architectures. By using ‘roles’ to explicitly fetch data either eagerly, lazily or some combination thereof, we can build fetching strategies to load accordingly when a role has been specified. The role can be reasoned as a business event of sorts. Udi has written extensively on this and developed a method for using fetching strategies with NHibernate and if you haven’t yet checked out what he’s had to say to date on the subject I suggest you take a look.

With Entity Framework 4.0 I wanted to refine my approach taken with EF 1.0 previously. Fetching Strategies are a key component in the framework (which I call NFetchSpec4Ef) and helps me work in a manner that fit’s with my use of Domain Driven Design.

Demonstrate your intentions

Before we get to the strategies themselves we need some way to state our intent with regards to fetching data and so this leads us to Fetching Intentions.

public class EagerFetchingIntention
{
    private static EagerFetchingIntention _factory_intent;
    private readonly string _fetchAssociate;

    public string FetchAssociate
    {
        get { return _fetchAssociate; }
    }

    internal EagerFetchingIntention(string fetch)
    {
        _fetchAssociate = fetch;
    }

    private EagerFetchingIntention() { }

    public static EagerFetchingIntention
            CreateInstance<TRootEntity, TFetchEntity>
            (Expression<Func<TRootEntity, TFetchEntity>> fetch)
    {
        if(fetch == null)
            return new EagerFetchingIntention(string.empty);

        int dot = fetch.Body.ToString().IndexOf(“.”) + 1;
        string includes = fetch.Body.ToString().Remove(0, dot);

        _factory_intent =
            new EagerFetchingIntention(includes);

        return _factory_intent;
    }
}

We can chain intentions together with a fluent interface provided by an .And()extension method.

public static class EagerFetchingIntentionExtensions
{
    public static EagerFetchingIntention And(
                this EagerFetchingIntention original,
                EagerFetchingIntention addTo)
    {
        EagerFetchingIntention compound_intention;

        compound_intention =
            new EagerFetchingIntention(
                original.FetchAssociate +
                “.” + addTo.FetchAssociate);

        return compound_intention;
    }
}

Fetching Strategies Refactored

Like all parts of NFetchSpec4Ef, Fetching Strategies needed to be rethought as part of addressing the 4.0 changes to the Entity Framework and in particular it’s new support for POCO entities and (somewhat) implicit lazy loading. So what do Fetching Strategies look like now? Fetching Intentions remained (as seen above) but generally speaking the API changed somewhat.

public interface IFetchingStrategy
{
    IList<EagerFetchingIntention> Intentions { get; }
    IEnumerable<string> Includes { get; }
    void AddIntentions(EagerFetchingIntention[] intentions);
    bool ShouldLazyLoad { get; }
    bool HasInstructions { get; }
}

public interface IFetchingStrategy<TRole> : IFetchingStrategy { }

These two interfaces form the basis of Fetching Strategies in NFetchSpec4Ef. In the next version of NFetchSpec4Ef, the implementation no longer required implementing these interfaces directly when creating a new strategy, rather we inherit from a super class that has already done this for us. You might also notice that the aspects to this interface for non-public consumption have been hidden through explicit implementation.

public class FetchingStrategy : IFetchingStrategy
{
    private readonly IList<EagerFetchingIntention> _intentions;
    private readonly bool _includeDeferedLoading = default(bool); 

    public FetchingStrategy(bool useDeferedLoading)
    {
        _includeDeferedLoading = useDeferedLoading;
        _intentions = new List<EagerFetchingIntention>();
    }

    private FetchingStrategy() { }

    public void AddIntentions(EagerFetchingIntention[] intentions)
    {
        if ((intentions == null) || (intentions.Count() < 1))
            return;
        intentions.ToList().ForEach(i => _intentions.Add(i));
    }

    public IEnumerable<string> Includes
    {
        get
        {
            if(((IFetchingStrategy)this).HasInstructions == false)
                return new List<string>().AsEnumerable();

            IEnumerable<String> includes =
                (from intents in _intentions
                select intents.FetchAssociate).AsEnumerable();
            return includes;
        }
    }

    IList<EagerFetchingIntention> IFetchingStrategy.Intentions
    {
        get { return _intentions; }
    }

    bool IFetchingStrategy.ShouldLazyLoad
    {
        get { return _includeDeferedLoading; }
    }

    bool IFetchingStrategy.HasInstructions
    {
        get { return _intentions.Count > 0 || _includeDeferedLoading; }
    }
}

Our goal includes notifying our infrastructure of our fetching intent by being explicit through the use of roles which have been defined as Interfaces. The infrastructure is able now to employ IoC / DI to locate the most appropriate Fetching Strategy from a container. This frees us to swap out fetching details for specific business events, after all, in some situations such as “IMakeCustomerPreferred” (see below), I might want to eager fetch all my customers orders and order lines in one go. Here’s the base class implementation of IFetchingStrategy<T> for role based fetching strategies,  followed by a custom Fetching Strategy:

public abstract class FetchingStrategyForRoles<TRole> :
        FetchingStrategy, IFetchingStrategy<TRole>
{
    public FetchingStrategyForRoles(bool useDeferedLoading) :
        base(useDeferedLoading) { SetupIntentions(); }

    public abstract void SetupIntentions();
}
class CustomerPreferedFetchingStratey :
        FetchingStrategyForRoles<IMakeCustomerPrefered>
{
    public CustomerPreferedFetchingStratey()
        : base(false) { }

    public override void SetupIntentions()
    {
        var orders_intention =
            EagerFetchingIntention
            .CreateInstance<Customer, IList<Order>>(c => c.Orders);
        var orderlines_intention =
            EagerFetchingIntention
            .CreateInstance<Order, IList<OrderLine>>(o => o.OrderLines);

        var iFetch = this as IFetchingStrategy;

        iFetch.AddIntentions(new EagerFetchingIntention[]
            {
                orders_intention,
                orders_intention.And(orderlines_intention)
            });
    }
}
This custom strategy will produce two “includes” strings for ObjectQuery<T> to work with, “Orders” and “Orders.OrderLines”. From the consumers point of view we would be writing code that looked something like this:
var repo =
    new EntitiesRepository<NorthwindEntities, Customer>
        (new NorthwindEntities());

repo.Get<IMakeCustomerPreferred>();

We leave the container (IoC) to deal with locating the right fetching strategy based on the role of IMakeCustomerPrefered. The dependency injection happens inside of the Repository.

The next part of NFetchSpec4Ef to discuss will be how Specifications fit in and what they offer to Repositories.

Update March 19th 2010:

If you are interested further in using Fetching Strategies with the Entity Framework, then you might find this series of posts interesting.

Helping the Entity Framework Play it’s <Role> Part 1.0

Helping the Entity Framework Play it’s <Role> Part 2.0

Helping the Entity Framework Play it’s <Role> Part 3.0

Helping the Entity Framework Play it’s <Role> Part 4.0

Share/Save/Bookmark

4 comments

Entity Framework 4.0 Improvements

First up, let me just say that I’m quite pleased that my needs with respect to declaring my fetching intentions (eager and / or lazy), no longer will require the  assistance of hammer_and_nail2-211x300PostSharp to get the job done. PostSharp is a great tool but I really shouldn’t have had to use it to achieve working the way I wanted to, therefore POCO is a welcome addition even if it does force me into some things such as choosing ICollection for 1..M navigable relationships within my Domain Model (only if you want to use change tracking proxies).

I am not going to regurgitate the changes here, for a complete list of the changes and new features see the ADO.Net Team blog.

There seem to be several points along an axis of how POCO you can choose to be with Entity Framework 4.0. At this stage I have the feeling that I will fall into the camp that probably wont use the proxies for change tracking but I will reserve judgement on that and perhaps that decision will be best left as a case by case assessment for some.

The thing I like the most is the fact I can (as already stated) remove the smoke and mirrors from my past efforts to get (somewhat) transparent lazy loading and streamline my whole approach. I say ‘somewhat’ transparent due to the fact that DeferedLoading is still ultimately ‘opt in’ and hence if you wanted to be pedantic you could make a case that this is still explicit. See below.

context.ContextOptions.DeferredLoadingEnabled = true

I will follow up from this post will several more by examining  each constituent part in the new version of NFetchSpec for the Entity Framework version 4.0. NFetchSpec4Ef, provides a reusable approach to implementing Repositories, Fetching Strategies and Specifications. Fetching Strategies provide a unified way of declaring your intent when instructing the Entity Framework to fetch data. Specifications enables a functional approach to supplying dynamic query predicates and stays true to the patterns original intent, that being to provide a means to testing that an entity satisfies a given set of conditions. Repositories speak for themselves.

Share/Save/Bookmark

2 comments

Doing .Net Days is full for August 2009

Thanks to everyone who has registered for the very first “doing .Net days” event. All seats for August are now filled, I will however post a notice if any positions re-open.

Looking forward to seeing everyone there.

Share/Save/Bookmark

No comments

Next Page »

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