title: IQueryable<T>.Include(string path) not modifying query to include joins
body: <p>Using Entity Framework 5, I have a generic method that retrieves entities from my context with optional parameters to filter, include related entities, and set the order of results. When I pass the method a set of include properties, however, it never modifies the query with joins to include the related entities. Any ideas why my query isn't updating?</p>
  
  <p>Method:</p>
  
  <pre><code>public virtual IQueryable&lt;TEntity&gt; Get(
      Expression&lt;Func&lt;TEntity, bool&gt;&gt; filter = null,
      string includeProperties = "",
      Func&lt;IQueryable&lt;TEntity&gt;, IOrderedQueryable&lt;TEntity&gt;&gt; orderBy = null)
  {        
      IQueryable&lt;TEntity&gt; query = dbSet.AsExpandable();
  
      if (filter != null)
      {
          query = query.Where(filter);
      }
  
      foreach (var includeProperty in includeProperties.Split
          (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
      {
          query = query.Include(includeProperty);
      }
  
      if (orderBy != null)
      {
          return orderBy(query);
      }
      else
      {
          return query;
      }
  }
  </code></pre>
  
  <p>Query before <code>foreach (var includeProperty...</code> that remains unchanged afterwards</p>
  
  <pre><code>{SELECT 
  [Extent1].[Pid] AS [Pid],     
  [Extent1].[Created] AS [Created], 
  [Extent1].[Creator] AS [Creator]
  FROM [Administrator] AS [Extent1]}
  </code></pre>
  
  <p><strong>EDIT...More Info</strong></p>
  
  <p>Originally I was using the following method call: <code>AdministratorDTO admin = unitOfWork.AdministratorComponent.GetByID(userPid);</code> on the following POCO class:</p>
  
  <pre><code>public virtual TEntity GetByID(object id)
  {
      return dbSet.Find(id);
  }
  
  public class Administrator : IPrincipal
  {
      [Key]
      [Required]
      [StringLength(1024)]
      [Display(Name = "PID")]
      public string Pid { get; set; }
  
      public DateTime Created { get; set; }
  
      public string Creator { get; set; }
  
      ...
  
      public ICollection&lt;Role&gt; Roles { get; set; }
  
      public ICollection&lt;Area&gt; Areas { get; set; }
  
      ...
  }
  </code></pre>
  
  <p>And using AutoMapper to map to a DTO with the following configuration:</p>
  
  <pre><code>public class AdministratorDTO
  {
      [Key]
      [Required]
      [StringLength(1024)]
      [Display(Name = "PID")]
      public string Pid { get; set; }
  
      ...
  
      public string[] Roles { get; set; }
  
      public string[] Areas { get; set; }
  }
  
  
  public class WebApiApplication : System.Web.HttpApplication
  {
  ...
  AutoMapperConfiguration.Configure();
  }
  
  public static class AutoMapperConfiguration
  {
      public static void Configure()
      {
          ConfigureAdministratorMapping();
          ...
      }
  
      private static void ConfigureAdministratorMapping()
      {
          Mapper.CreateMap&lt;Administrator, AdministratorDTO&gt;()
              .ForMember(dest =&gt; dest.Roles, 
                  opt =&gt; opt.MapFrom(src =&gt; src.Roles == null ? 
                      null : src.Roles.Select(r =&gt; r.Name).ToArray())) 
              .ForMember(dest =&gt; dest.Areas, 
                  opt =&gt; opt.MapFrom(src =&gt; src.Areas == null ?
                      null : src.Areas.Select(a =&gt; a.Id).ToArray()));
  
          ...
      }
  }
  
  public class BusinessComponent&lt;TEntity, TDto&gt; 
      : IBusinessComponent&lt;TEntity, TDto&gt;
          where TEntity : class
          where TDto : class
  {
      ...
      protected TDto Flatten(TEntity entity)
      {
          return Mapper.Map&lt;TEntity, TDto&gt;(entity);
      }
  }
  </code></pre>
  
  <p>My understanding was that if I didn't mark the <code>Administrator</code>'s navigation properties (Areas and Roles) as <code>virtual</code> they would be eagerly loaded, but I kept getting an empty string[] in my DTO.</p>
  
  <p>I looked at the TEntity parameter going into my <code>Flatten</code> method and Areas/Roles were <code>null</code> <em>before</em> I called <code>Map</code>, so I don't think it was something to do with AutoMapper.</p>
  
  <p>Next I tried using the following method call:</p>
  
  <pre><code>AdministratorDTO admin = unitOfWork.AdministratorComponent
      .Get(filter: a =&gt; a.Pid == "csherman", includeProperties: "Roles, Areas")
      .SingleOrDefault();
  </code></pre>
  
  <p>Finally, just in case the <code>Include</code> was being ignored because the navigation properties were not <code>virtual</code>, I added the <code>virtual</code> keyword to both <code>Areas</code> and <code>Roles</code> on my <code>Administrator</code> class. When I did this, both the <code>GetByID</code> and the <code>Get(filter: ..., includeProperties: ...)</code> methods worked, thereby including the Areas/Roles in my TEntity <code>Flatten</code> parameter and populating the string arrays in my DTO.</p>
  
  <p>Problem solved I suppose, but...</p>
  
  <p>Question is, especially for the <code>GetById</code> method, why did it work with the <code>virtual</code> keyword but <em>not</em> without?</p>
  
  <p>If EF actually factors in the projection from the time of the original method call, why would these entities be included?</p>