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://mcmap.net/q/127769/-ef-linq-include-multiple-and-nested-entities This is similar what I want but it uses string instead of delegates.
https://mcmap.net/q/1963698/-pass-a-lambda-parameter-to-an-include-statement 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://mcmap.net/q/2036798/-entity-framework-multiple-include-at-runtime 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.
aa
is a queryable that hasn't executed yet. If the final query'sSelect
touches on any related entities, they'll be loaded as well, even withoutInclude
. Second, sinceaa
is a queryable, you can "append"Include
orWhere
calls as needed, egforeach(var exp in expressions){ aa=aa.Include(exp);}
– PubliusInclude
calls dynamically would be if you were trying to create a dynamic query generator without actually knowing what the type is. Since you already know what the type is though, trying to "parameterize" the calls will end up more verbose than simply using theInclude
calls you need in each case. – PubliusInclude()
s were the worst compromise you could ask for. It had to be the union of everything since the poor method could not be certain which linked entity might be used. – Hatchetaa
is still an incomplete query. You need to either iterate over it or useToList()
,ToArray()
etc to execute it. If you write aSelect
that needs the related entities, they'll be loaded. – PubliusInclude()
is if you tried to load all objects from the database without filtering. Which is extremely rare and typically an indicator of a bug - perhaps an attempt to force client-side evaluation? The answer shows that anIncludeMultiple
is no better than actually writing theInclude
calls too – PubliusInclude()
s and returned theIQueryable
, egpublic IQueryable<Transaction> TransactionsGraph=>Transactions.Include(p=>..).Include(p=>...);
– PubliusAfter that
that's the problem. Why don't you transform the objects in the LINQ query, and avoid loading unwanted data? Have you tried and got errors complaining the expression can't be converted to SQL? That's your actual problem, notInclude
. Post the transformation code and the errors you got. There are always ways to bypass the problem, possibly by loading an intermediate form of just the data you need in theSelect
. Tools like AutoMapper can even work with EF queries directly to simplify mapping – Publius