2

I have a Entity Framework model where I have a user which has the following relationships:

User 1-* Test

Each Test has the following relationships:

Test 1-1 Course
Test 1-* TestEvent

I have a service that returns a user and at different points in my application I want to eagerly fetch various relationships. I am fetching all the relationships at present:

var result = (from appUser in context.AppUsers.Include("Tests.Course")
    .Include("Tests.TestEvents")
    where appUser.Login.ToLower() == loginName.ToLower() &&
    appUser.IsDeleted == false
    select appUser).FirstOrDefault();

I do not want to always return the Course linked to a Test or the TestEvents. How can I build an ObjectQuery and dynamically add the Include statements as required rather than having a series of if else statements.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Gary Joynes
  • 656
  • 7
  • 23

1 Answers1

5

Well, since Include returns an IQueryable<T> (LINQ chainable), i would use a simple extension method:

public static IQueryable<T> WithIncludes<T>(this IQueryable<T> source, string[] associations)
{
   var query = (ObjectQuery<T>)source;

   foreach (var assoc in associations)
   {
      query = query.Include(assoc);
   }
}

Then your query looks like this:

var inclusions = new[] { "Tests.Course", "Tests.TestEvents" };
var result = ctx.AppUsers
                .WithIncludes(inclusions)
                .Where(x => x.Login.ToLower() == loginName.ToLower())
                .Where(x => !x.IsDeleted)
                .FirstOrDefault();

To get some strong-typing into the otherwise magic-string nature of include, i have specialized enums for all associations, so i pass an [] of those through and convert the enum to the string include.

The thing is, your methods should define what inclusions are required. So first thing you do in the method is declare what associations are required, then pass that to your extension method.

Is that what your after?

Gary Joynes
  • 656
  • 7
  • 23
RPM1984
  • 72,246
  • 58
  • 225
  • 350
  • @Garg Joynes - no problems, let me know if you have any issues. – RPM1984 Dec 27 '10 at 21:37
  • @RPM1984 - sorry for the delay. The solution is perfect, many thanks. I also used the solution from http://stackoverflow.com/questions/632434/linq-to-sql-where-clause-optional-criteria to handle Where clauses in the same way – Gary Joynes Mar 12 '11 at 07:32
  • Nice, this will benefit my projects greatly! – MvcCmsJon May 17 '11 at 02:46
  • 1
    @MvcCmsJon - keep in mind, if your on the new version of EF, there is strongly-typed `Include`, so this is no longer required. – RPM1984 May 17 '11 at 03:35
  • @RPM1984 - Thanks, I couldn't find a hard reference to what you mean, are you talking about [this](http://tomlev2.wordpress.com/2010/10/03/entity-framework-using-include-with-lambda-expressions/) – MvcCmsJon May 22 '11 at 05:38
  • @RPM1984 - I found what you are talking about 4.1 the new new new version. Thanks! will check it out. – MvcCmsJon May 22 '11 at 05:52