Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I construct a function that allows me to pass in several includes for EF via params?

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!

like image 392
Bigsby Avatar asked Oct 27 '25 06:10

Bigsby


2 Answers

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?

like image 166
Carl Prothman Avatar answered Oct 28 '25 20:10

Carl Prothman


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.

like image 24
InteXX Avatar answered Oct 28 '25 21:10

InteXX



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!