0

I want to build up an object graph using Entity Framework 4.2.

Right now, I have POCO entities, using ICollection for navigation properties. I want to avoid using EntityCollection or anything EF-specific.

I want to avoid massive joins caused by using Include excessively. Given an object, I want to populate its navigation properties, resulting in a separate database query.

Is there a way to populate an ICollection directly? Right now, I am working around the problem, but it is really painful.

// grab the user, brand users and brands
User user = entities.Users
                    .Include(item => item.BrandUsers.Select(brandUser => brandUser.Brand))
                    .Where(item => item.Name == userName)
                    .SingleOrDefault();
// grab the pending share grants and brands
entities.Users
        .Include(item => item.ToShareGrants.Select(shareGrant => shareGrant.Brand))
        .Where(item => item.Id == user.Id)
        .Load();
return user;

One thing I don't like about this approach is that I am re-querying the top-level object. If I don't do this, the navigation property isn't populated (left NULL) when there are no objects returned. For instance, the following code only works if results are returned:

entities.ShareGrants
        .Include(item => item.Brand)
        .Where(item => item.ToUserId == user.Id)
        .Load();

I was curious if there was just a method I wasn't aware of in entity framework for building these types of relationships. If anyone knows an easy approach to filling out navigation properties in steps, I'd appreciate a code sample.

Travis Parks
  • 8,435
  • 12
  • 52
  • 85

3 Answers3

0

The short answer to this question is that EF4 did not directly support the functionality I wanted. In order to prevent a massive join and break the results out across multiple calls to the database, the top-most entity must be downloaded from the database again. This means the left-most columns in the result set will be the columns of that entity repeated for each record.

Travis Parks
  • 8,435
  • 12
  • 52
  • 85
0

Try turn off lazy loading for your current query, you may just put this in a using block

entities.ContextOptions.LazyLoadingEnabled = false;
zs2020
  • 53,766
  • 29
  • 154
  • 219
  • I have lazy loading and proxy generation turned off. It seems Include is the only way to populating navigation properties. What I am looking for is a way to explicitly load navigation properties (via a database query). – Travis Parks Jan 27 '12 at 01:02
0

Your question is not very clear. Why not use multiple Includes in the same query

User user = entities.Users
      .Include(item => item.BrandUsers.Select(brandUser => brandUser.Brand))
      .Include(item => item.ToShareGrants.Select(shareGrant => shareGrant.Brand))
      .Where(item => item.Name == userName)
      .SingleOrDefault();
Eranga
  • 32,181
  • 5
  • 97
  • 96
  • If I use multiple Includes, it can cause a massive join. Also, I may conditionally build up different parts of the object graph, depending on what's needed. – Travis Parks Jan 27 '12 at 00:52
  • @TravisParks If you do not load them upfront, loading each navigational property will issue a database request. Each approach has its trade off, choose whats best for each case. – Eranga Jan 27 '12 at 01:23
  • I want a database hit, in my scenario. – Travis Parks Jan 27 '12 at 02:25