I'm writing an EF-backed repository that has a concept of packages associated to each entity type that does .Include for its commonly used children. For example, I have a function that looks like this
private static IQueryable<Foo> GetFooPackage(Entities context)
{
return context.Foo
.Include(target => target.Bar)
.Include(target => target.FooBar)
}
This is so when I run my "get" methods, there's a consistent grouping of returned data. However, I want to be able to expand on that on a case by case basis. I want to be able to do something like
public static Foo GetFoo(int fooId, params Expression<Func<Foo, T>>[] extraIncludes)
{
using (Entities context = GetContext(null))
{
IQueryable<Foo> package = GetFooPackage(context);
extraIncludes.ToList().ForEach(expression => package.Include(expression));
return package.FirstOrDefault(target => target.FooId == fooId);
}
}
What's hanging me up is the T portion. I know the example doesn't properly reference the T generic. It's just a placeholder for the example. I'm unsure how to shape that so that I can do what I want. Ultimately, it's an effort to keep the SQL generated by EF as small and neat as possible. What would you suggest? It's being used in a disconnected service so I can't rely on lazy loading to simply fetch more data if it's missing. Once I grab the data, I need to get it in one go, and doing a second fetch really wouldn't be practical.
Thanks!
public IQueryable<T> GetAllIncluding(params Expression<Func<T, object>>[] includes)
{
var query = DbSet.AsNoTracking();
query = includes.Aggregate(query, (current, includeProperty) => current.Include(includeProperty));
return query;
}
MyGenericRepository<A>().GetAllIncluding(x=> x.B, x=> x.C).FirstOrDefault()
Answer found here: How to include 2 navigational properties in EF?
For those unable to use the accepted answer due to DbSet.AsNoTracking, here's an alternative:
public IEnumerable<TEntity> Retrieve(params Expression<Func<TEntity, object>>[] relations)
{
IQueryable<TEntity> query = this.Entities;
foreach (var relation in relations)
query = query.Include(relation);
return query;
}
This version loops through the array of relations and expands the query with each iteration.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With