Come posso implementare più Include in Entity Framework?

Aug 24 2020

Uso Entity Framework 6. Ho un oggetto Transaction con diverse proprietà di navigazione. È facile implementare il caricamento desideroso utilizzando più Include.

 var aa = db.Transactions.Include(p => p.Account).Include(p => p.Instrument);

Come posso implementare lo stesso se i campi da includere sono parametri?

var aa = db.Transactions.IncludeMore(delegatesToBeIncluded);   

Se delegatesToBeIncludedè nullo, non c'è niente da includere.

https://stackoverflow.com/a/38823723/5852947 Questo è simile a quello che voglio ma usa la stringa invece dei delegati.

https://stackoverflow.com/a/35889204/5852947 Anche questo è interessante.

Come passare lambda "include" con più livelli in Entity Framework Core? Questo si concentra su più livelli (ho un livello)

https://stackoverflow.com/a/52156692/5852947 Anche questo è promettente.

Quale direzione dovrei andare?

Revisione 1 : perché ne ho bisogno? Sulla base degli elementi di aanuovi oggetti verranno creati. Mi sono reso conto che ad ogni creazione di un oggetto EF legge il DB (viene utilizzato il caricamento lento). È di soli 50 ms, ma viene ripetuto n volte. Questa funzione è implementata in una classe modello, quindi anche Transazioni è un parametro.

Revisione 2 : nel codice completo c'è il filtraggio (impaginazione per essere esatti) e ToList () alla fine. La parte difficile che è implementata in una funzione template. dbTableSelectorè un delegato:readonly Func<MainDbContext, DbSet<TDbTable>> dbTableSelector;

 var myList = dbTableSelector(db).Where(WhereCondition).
             Skip(numberOfSkippedRows).Take(PageSize).OrderBy(OrderByCondition).ToList();

Dopodiché trasformo ogni elemento di myListin un altro tipo di oggetto. Qui è dove il caricamento lento viene attivato uno per uno per ogni elemento. Questo è il motivo per cui provo a utilizzare Include. Se dbTableSelector(db)ritorna Transactionsdevo includere diversi elementi quando ritorna, diciamo Instruments. Quindi IncludeMore dovrebbe avere un parametro List che definisce i campi da includere.

Risposte

IstvanHeckl Aug 27 2020 at 08:58

Ecco la soluzione. Si basa su questo .

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;
    }
}

Questa è la chiamata:

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);