I use Entity framework 6. I have a Transaction object with several navigation properties. It is easy to implement eager loading using multiple Include.
var aa = db.Transactions.Include(p => p.Account).Include(p => p.Instrument);
How can I implement the same if the fields to be included are parameters?
var aa = db.Transactions.IncludeMore(delegatesToBeIncluded);
If delegatesToBeIncluded
is null then there is nothing to be included.
https://stackoverflow.com/a/38823723/5852947 This is similar what I want but it uses string instead of delegates.
https://stackoverflow.com/a/35889204/5852947 This is also interesting.
How to pass lambda 'include' with multiple levels in Entity Framework Core? This focuses on multiple level (I have one level)
https://stackoverflow.com/a/52156692/5852947 This is promising also.
Which direction should I go?
Revision 1: Why I need this?
Based on the elements of aa
new objects will be created. I realized that at each object creation EF reads the DB (lazy loading is used). It is just 50 ms, but it is repeated n times.
This function is implemented in a template class, so Transactions is also a parameter.
Revision 2: In the full code there is filtering (pagination to be exact), and ToList() at then end. The tricky part that it is implemented in a template function. dbTableSelector
is a delegate: readonly Func<MainDbContext, DbSet<TDbTable>> dbTableSelector;
var myList = dbTableSelector(db).Where(WhereCondition).
Skip(numberOfSkippedRows).Take(PageSize).OrderBy(OrderByCondition).ToList();
After that I transform each element of myList
to another type of object. This is where lazy loading is activated one by one for each element. That is why I try to use Include. If dbTableSelector(db)
returns Transactions
I have to Include different elements when it returns let us say Instruments
. So IncludeMore should have a List parameter which defines the fields to be included.
Here is the solution. It is based on this.
public static class IQueryableExtensions
{
public static IQueryable<T> IncludeMultiple<T, TProperty>(this IQueryable<T> query,
Expression<Func<T, TProperty>>[] includeDelegates) where T : class
{
foreach (var includeDelegate in includeDelegates)
query = query.Include(includeDelegate);
return query;
}
}
This is the calling:
var pathsA = new Expression<Func<ViewTransaction, object>>[2] { p => p.Account, p => p.Instrument };
var pathsB = new Expression<Func<ViewTransaction, object>>[1] { p => p.Account};
var pathsC = Array.Empty<Expression<Func<ViewTransaction, object>>>();
var a = db.ViewTransactions.IncludeMultiple(pathsA).Single(e => e.Id == 100);