Como posso implementar vários Include in Entity Framework?

Aug 24 2020

Eu uso o Entity framework 6. Eu tenho um objeto Transaction com várias propriedades de navegação. É fácil implementar o carregamento antecipado usando vários Include.

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

Como posso implementar o mesmo se os campos a serem incluídos são parâmetros?

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

Se delegatesToBeIncludedfor nulo, não há nada a ser incluído.

https://stackoverflow.com/a/38823723/5852947 Isso é semelhante ao que eu quero, mas usa string em vez de delegados.

https://stackoverflow.com/a/35889204/5852947 Isso também é interessante.

Como passar lambda 'incluir' com vários níveis no Entity Framework Core? Isso se concentra em vários níveis (eu tenho um nível)

https://stackoverflow.com/a/52156692/5852947 Isso também é promissor.

Que direção devo seguir?

Revisão 1 : por que preciso disso? Com base nos elementos de aanovos objetos serão criados. Percebi que a cada criação de objeto, o EF lê o banco de dados (o carregamento lento é usado). Tem apenas 50 ms, mas é repetido n vezes. Essa função é implementada em uma classe de modelo, portanto, Transações também é um parâmetro.

Revisão 2 : No código completo há filtragem (paginação para ser mais exato), e ToList () no final. A parte complicada é que ele é implementado em uma função de modelo. dbTableSelectoré um delegado:readonly Func<MainDbContext, DbSet<TDbTable>> dbTableSelector;

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

Depois disso, transformo cada elemento de myListem outro tipo de objeto. É aqui que o carregamento lento é ativado um por um para cada elemento. É por isso que tento usar Incluir. Se dbTableSelector(db)retorna Transactionseu tenho que incluir elementos diferentes quando ele retorna, digamos Instruments. Portanto, IncludeMore deve ter um parâmetro List que define os campos a serem incluídos.

Respostas

IstvanHeckl Aug 27 2020 at 08:58

Aqui está a solução. É baseado nisso .

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

Esta é a vocação:

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