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

19 thoughts on “Agile Entity Framework 4 Repository Part 5: IObjectSet and Include

  1. 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?

  2. 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.

  3. 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.

  4. 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?

  5. 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)

  6. 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…

  7. 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.

  8. @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?

  9. 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

  10. 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

  11. 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!

  12. 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 Reply

Your email address will not be published. Required fields are marked *


+ 7 = fifteen

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>