views:

343

answers:

2

I'm not sure if this is the right thing to do, I'm sure someone will tell me if it's not.

I asked a question (http://stackoverflow.com/questions/1662760/entity-framework-include-in-sub-query) earlier this evening, which was answered very well and has solved my problem. But, I think there could be a better way, so I'm going to re-ask the question, but slightly differently.

Let's say I have 3 tables:

Restaurant 1.....M MenuCategory 1.....M MenuItem I have a L2E query that looks something like this:

Restaurant = context.Restaurant .Include(r => r.MenuCategory) .FirstOrDefault(r => r.RestaurantId == resaurantId); Which works to some extent, but it only pre-loads the menu categories.

What I really want to be able to do is something like:

Restaurant = context.Restaurant
.Include(r => r.MenuCategory)
.Include(r => r.MenuCategory.MenuItems)
.FirstOrDefault(r => r.RestaurantId == resaurantId);

But clearly this isn't available as r.MenuCategory is an enumerable

...the work around is to use the standard notation:

context.Restaurant.Include("MenuCategory.MenuItems");

...but this is not strongly typed. This question is about finding a strongly typed answer

This is the current extension method:

public static ObjectQuery<T> Include<T>(this ObjectQuery<T> query, Expression<Func<T, object>> path)
{
    // Retrieve member path:  
    List<PropertyInfo> members = new List<PropertyInfo>();
    EntityFrameworkHelper.CollectRelationalMembers(path, members);

    // Build string path:  
    StringBuilder sb = new StringBuilder();
    string separator = "";
    foreach (MemberInfo member in members)
    {
        sb.Append(separator);
        sb.Append(member.Name);
        separator = ".";
    }

    // Apply Include:  
    return query.Include(sb.ToString());
}

How could this be adapted to allow a strongly typed form of:

context.Restaurant.Include("MenuCategory.MenuItems");
+3  A: 

I have a Tip that allows exactly this: Tip 28 - How to implement an eager load strategy

Uses a nifty trick I think.

Alex

Alex James
Perfect, exactly what I was after. I will have a play with that tonight then, may tweak it around a bit. Thank you!
Paul
I've just gotten this working and it's working perfectly. I created an extension method so that it can be used like ".IncludeStrategy(new MyStrategy())" rather than "from b in new BlogFetchStrategy().ApplyTo(ctx.Blogs) where b.Owner == “Alex” select b;"
Paul
Yeah that seems better. I was always a little unhappy with my approach. Your's is much better
Alex James
A: 

A far less elegant but much quicker to implement method might be as follows:

var list = dataContext.CartLists.Include(typeof(CartListItem).Name).Where(l => l.CustNum == customerNumber && l.ListTypeID == (int)ShoppingCartType.WebShoppingCart).Single();

. . . but you'll need to ensure that you haven't had the EF model generator pluralize your entity set names. This is kind of an ugly solution, but it should give you compile errors once you update your EF model if your table names ever change, as ours just did, and you won't have to actually execute your code to try to find places where your strings don't match actual entities.

Dave Falkner