Apply Include and ThenInclude based on Lambda Expressions Dictionary

c# entity-framework entity-framework-core

Question

I have a few Entity Framework 7 (Core) entities:

public class Person {
   public virtual Address Address { get; set; }
   public virtual ICollection<Hobby> Hobbies { get; set; }
}

public class Address {
   public String Street { get; set; }
   public virtual Country Country { get; set; }
}

And I have a string array as follows:

String[] entities = new String[] { "Hobbies", "Address.Country" }

Given this string array I got:

context.Persons
  .Include(x => x.Hobbies)
  .Include(x => x.Address).ThenInclude(x => x.Country);

In EF6 I could do something like:

context.Persons.Include(entities[0]).Include(entities[1]);

But in EF7 Include does not allow strings. I created the dictionary:

private readonly Dictionary<String, LambdaExpression> _properties = new Dictionary<String, LambdaExpression>();

Which would have something like:

x => x.Hobbies is for "Hobbies"
x => x.Address.Country is for "Address.Country"     

And I have the extension:

public static IQueryable<T> Include<T>(this IQueryable<T> source, Dictionary<String, LambdaExpression> properties) {
}

Where I need to given the Dictionary apply the following:

  1. For "x => x.Hobbies" just do:

     source.Include(x => x.Hobbies);
    
  2. If the expression is something like "x => x.Address.Country" add:

     source.Include(x => x.Address).ThenInclude(x => x.Country);
    

Can this be done?

1
1
7/4/2016 1:30:11 PM

Accepted Answer

Not sure about ThenInclude() and EF 7, but you can do something like this in your repositories (tested with EF 6):

public MyEntity GetMyEntity_EagerlyLoad(DbContext context, int id, params Expression<Func<MyEntity, object>>[] propertiesToLoad)
{
    var q = context.MyEntities.Where(m => m.ID == id);

    foreach (var prop in propertiesToLoad)
        q = q.Include(prop);

    return q.SingleOrDefault();
}

You can then call it like this:

repo.GetMyEntity_EagerlyLoad(context, id, m => m.Property1, m => m.Property2, m => m.Property1.NestedProperty)


EDIT: There is also the alternative way to do eager loading with EF using projection. You could do a generic repository method like this:

public MyEntity GetMyEntity_EagerlyLoad<T>(DbContext context, int id, Expression<Func<MyEntity, T>> loadingProjection, Func<T, MyEntity> resultProjection)
{
    var q = context.MyEntities.Where(m => m.ID == id);

    return q.Select(loadingProjection).AsEnumerable().Select(resultProjection).SingleOrDefault();
}

And then call it with the properties you want loaded and the entity you want the method to return:

repo.GetMyEntity_EagerlyLoad(context, id, m => new { myEntity = m, m.Property1, m.Property2, m.Property1.NestedProperty }, m => m.myEntity)
0
7/6/2016 8:26:20 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow