Agile Entity Framework 4 Repository Part 5: IObjectSet and Include

  1. Agile Entity Framework 4 Repository: Part 1- Model and POCO Classes
  2. Agile Entity Framework 4 Repository: Part 2- The Repository
  3. Agile EF4 Repository: Part 3 -Fine Tuning the Repository
  4. Agile EF4 Repository: Part 4: Compiled LINQ Queries
  5. Agile Entity Framework 4 Repository Part 5: IObjectSet and Include
  6. Agile Entity Framework 4 Repository: Part 6: Mocks & Unit Tests

In Part 2 of this blog series, I created a context interface, IBAGAContext, that returns IObjectSet types rather than ObjectSet types from the EntitySets.

Example:

     IObjectSet<Contact> Contacts{get;}
     IObjectSet<Customer> Customers {get;}
    

IObjectSet is the new EF4 interface that is used to create the ObjectSets returned by the default context.

For a point of comparison, here’s a method from a default code generated context:

 public ObjectSet<Activity> Activities
        {
            get
            {
                if ((_Activities == null))
                {
                    _Activities = base.CreateObjectSet<Activity>("Activities");
                }
                return _Activities;
            }
        }
        private ObjectSet<Activity> _Activities;

ObjectSet implements IObjectSet which provides it with set operations. It also inherits from QueryObject which gives it lots of EF capabilities. One of the methods that come with QueryObject is Include which provides eager loading.

context.Customers.Include(“Orders”) blah blah

(A few people, including Matthieu Mezil, have created overloads for Include that take lambdas instead of magic strings. Here’s Matthieu’s second of two posts which contains a link to the first: Entity Framework Include with Function Next. Additionally, Jamie Philips had a lambda function for EF1 that allowed further filtering. Last time we talked, he reported that it wasn’t working with EF4 POCOs.)

But Include is not available with IObjectSet.

In a recent comment, Nick asked how I was using Include on an IObjectSet.I realize I neglected to add that into the relevant post.

With nods to Jamie Phillips again, Include came from his POCO sample when he and I co-presented back-to-back EF4 POCO sessions at the New England Code Camp in October.

Jamie created an Include extension method to replace the Include supplied by the ObjectQuery. I placed the method in a separate class file in the same project that contains the model and the BAGAContext file because it simply calls the real ObjectQuery.Include.

namespace ExtensionMethods
{
  public static class MyExtensions
  {
    public static IQueryable<TSource> Include<TSource>
      (this IQueryable<TSource> source, string path)
    {
      var objectQuery = source as ObjectQuery<TSource>;
      if (objectQuery != null)
      {
        return objectQuery.Include(path);
      }
      return source;
    }
  }
}

In the repositories in Part 3 of this series, this is how I was able to use the Include method.

Jamie did write a follow-up post about the problem with the lambdas and POCO classes: Include() Extension Method and POCO

Shout it
#1 Nick on 12.09.2009 at 8:15 AM

That's what I am looking for,

Thanks a lot Julie

#2 Michael Paterson on 12.09.2009 at 10:17 AM

I discovered this little nuance last night. I'm not a fan of IObjectSet not including "Include".

#3 Dmitry on 12.10.2009 at 2:39 PM

It is very strange that the interface does not include the Include method. What would be the advantage of exposing IObjectSet instead of IQueryable in the context?

#4 Steve Ward on 12.10.2009 at 6:45 PM

And what about user defined functions? Using this pattern, would i need to create a method on the context for each SP and have it call ExecuteFunction? Apparently ExecuteFunction is Public now but it isnt exposed as part of my context interface so I cant call it from my repository.

#5 Daniel Wertheim on 12.14.2009 at 6:09 PM

Hi!

I like your inspiring posts and I'm looking forward to read the new book.

I have written some stuff about how you could put EF4 code-only to work in an business application, along with WCF and IoC etc.

If anyone is interested you can check it out at: daniel.wertheim.se/.../putting-entity-

//Daniel

#6 CodeHulk on 1.22.2010 at 5:23 PM

Ok Julie, I love the content.

But, I am fairly certain that with the exception of the last post in this series, ALL of them had mentioned they would discuss testing in the next post. I quickly jump to the next AND STILL NO TESTING. :) Whats a guy gotta do to get a little TDD love.

#7 duncan on 3.01.2010 at 6:13 PM

Loving the series. Convinced now to buy your new book as soon as it is out.

Can't wait.

#8 Adam on 4.07.2010 at 5:58 PM

Agree with CodeHulk - Julie, do you have any unit tests you could share?

Specifically, how would you go about mocking your context to expose these IObjectSet<T> collections?

#9 Adam on 4.07.2010 at 10:58 PM

Here's a link to what seems to be a fantastic demo of unit-testing with EF4. The key part is their implementation of IObjectSet<T> - FakeObjectSet<T>, which turns out to be trivial. Once you have that, you have an in-memory LINQ repository, and unit testing should be cake (notwithstanding the occasional difference between LINQ-to-entities, and LINQ-to-Objects, which a commenter noted, but still.)

<a href='http://blogs.msdn.com/adonet/pages/walkthrough-test-driven-development-with-the-entity-framework-4-0.aspx'> blogs.msdn.com/.../a>

(hope that formatted correctly)

#10 Adam on 4.07.2010 at 10:59 PM

sorry:

blogs.msdn.com/.../walkthrough-tes

#11 Julie on 4.08.2010 at 9:49 AM

OKAY - I posted it here.

thedatafarm.com/.../agile-entity-fr

#12 Adam on 4.08.2010 at 10:48 AM

Thanks Julie - sorry to have pulled you away - now go finish that book so I can buy it :-D That you present unit testing in your book shows just how much better it is than the Apress one I'm reading now...

#13 Julie on 4.08.2010 at 10:54 AM

I didn't realize I had let that linger for months and months. Thanks for the reminder.

#14 Marc on 4.16.2010 at 2:11 PM

Hi Julie

I am having a problem using this approach with a Compiled Query. I am getting the following error:

LINQ to Entities does not recognize the method 'System.Linq.IQueryable`1[MyPocoObject] Include[MyIncludedPocoObject](System.Linq.IQueryable`1[MyPocoObject], System.String)' method, and this method cannot be translated into a store expression.

I don't get this error when my ObjectContext returns ObjectSet<T> rather than IObjectSet<T>. This works beautifully when the query is not compiled.

#15 Julie on 4.16.2010 at 2:16 PM

@marc

Hard to know what is different about your code than what I did. Mine definitely works. I'm trying so hard to finish my book and stay focused. Seems that its just a misuse of compiled queries. Precompiling is common to Linq to Entities and LINQ to SQL. Any chance you can ask on one of the MSDN forums or stackoverflow or something?

#16 Marc on 4.16.2010 at 2:56 PM

Thanks for your quick response Julie. I will ask on one of those forums. I didn't see in your posts where you were using a Compiled Query that called the include extension method so I wasn't sure if you had covered that. Any chance I can get the source code demonstrating this?

Also, thanks much for your great posts on EF4. They are a big reason why we are migrating off of linq-sql.

Marc

#17 Angelo on 4.21.2010 at 7:21 PM

Hi Julie

I would like to know which part can I apply the static class for the Include so that i can use in this in the query repository. Sorry for a stupid questions.

thanks

#18 Paul on 8.08.2010 at 3:06 PM

Hi Julie -

I have the same question as Marc and from what I can tell from his unanswered question on stackoverflow (http://stackoverflow.com/questions/3432484/entity-framework-4-iobjectset-include) no one knows the answer. Here is a code sample that generated the error:

private static readonly Expression<Func<Database, string, IEnumerable<SiteAnnouncement>>> expression = (database, slug) => database.SiteAnnouncements.Include("UserCreated").Where(sa => sa.Site.Slug == slug);

private static readonly Func<Database, string, IEnumerable<SiteAnnouncement>> plainQurey = expression.Compile();

private static readonly Func<Database, string, IEnumerable<SiteAnnouncement>> compiledQuery = CompiledQuery.Compile(expression);

When this is called with a .ToList() the error is thrown. Any ideas?

Cannot wait for your second book!

#19 Rab on 8.18.2010 at 7:16 PM

Hey Julie -

Really enjoyed reading your blog, the Include hack was the last piece in solving something very similar that I was trying to do myself - a T4 Visual Studio code generator that makes strongly typed mocking contexts for unit testing.

I'd thought I'd let you know in case you thought that I'd ripped you off.

I've linked back to your site to give you just credit.

Rab

Leave a Comment