Living in the Tech Avalanche Generation

A practitioner’s introspective on technology
Archive for February 11th, 2009

The Entity Framework and a unified Lazy and Eager loading framework.

I am in the middle of spiking a solution that aims to unify an approach to lazy and eager loading with the Entity Framework. I was ready to give up on the idea a while back but I am a stubborn PITA. It has been my goal for a while to try get Specifications, Repositories and (finally) Fetching Strategies bundled into a single approach for the Entity Framework. What I want to be able to do is write code like this:

public void Multi_Level_Mixed_Hierarchy_With_Persisting_Test()
{
    EntitiesRepository<Customer, NorthwindEntities> repos =
        new EntitiesRepository<Customer,
            NorthwindEntities>(new NorthwindEntities());

    Specification<Customer> german_cust_spec =
        new Specification<Customer>(c => c.CustomerID == “ALFKI”);

    var german_custs = repos.AllAsIList(“Customers”, german_cust_spec, new
                        MultiLevelMixedStrategy());

    foreach (var cust in german_custs)
    {
        cust.Country = “Italy”;
        Console.WriteLine(“The Customer Name is {0}”, cust.CompanyName);
        foreach (var order in cust.Orders)
        {
            order.ShipName = “The big boat”;
            Console.WriteLine(“\tThe Order ID is : {0}”, order.OrderID);
            foreach (var orderline in order.Order_Details)
            {
                orderline.Discount = 0.13f;
                Console.WriteLine(“\t\tThe value ordered for ” +
		    “Product ID {0} is {1}”,
                    orderline.Product.ProductID,
                    orderline.UnitPrice * orderline.Quantity);
            }
        }
    }

    repos.Session.SaveChanges();
}

The Repository and the Specification aspects to this unified approach have previously been developed and documented but the missing piece that has been outstanding is the Fetching Strategy. You can see above in the call to the repository .AllAsIList() method, that the third argument is the Fetching Strategy of which I speak.

public interface IFetchingStrategy
{
    IList<FetchingIntention> Intentions { get; }
}

public interface IFetchingStrategy<TRole> : IFetchingStrategy { }

And the implementation is:

public class MultiLevelMixedStrategy :
    IFetchingStrategy
{
    private readonly IList<FetchingIntention> _intentions =
        new List<FetchingIntention>();

    public MultiLevelMixedStrategy()
    {
        this.Intentions.Add(new FetchingIntention(“Orders”,
                                FetchMode.Eager));
        this.Intentions.Add(new FetchingIntention(“Orders.Order_Details”,
                                FetchMode.Eager));
        this.Intentions.Add(new FetchingIntention(“Product”,
                                FetchMode.Lazy));
    }

    public IList<FetchingIntention> Intentions
    {
        get { return _intentions; }
    }
}

Where the Entity Model looks like this:

ef_with_box_and_dice

So far the results look promising. I will have more to say on this shortly and with a bit of luck will be releasing the code which rounds out the triad of a Repository, dynamic querying capability via Specifications and Fetching Strategies for a unified approach for lazy and eager loading that does NOT require you ever explicitly call the .Includes(), Load() or IsLoaded methods and property on the EntityCollection<T>, EntityReference<T> or ObjectQuery<T> objects.

Share/Save/Bookmark

13 comments

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