Entity Frameworkに複数のインクルードを実装するにはどうすればよいですか?

Aug 24 2020

Entity Framework6を使用しています。いくつかのナビゲーションプロパティを持つTransactionオブジェクトがあります。複数のインクルードを使用して、積極的な読み込みを実装するのは簡単です。

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

含まれるフィールドがパラメーターである場合、どうすれば同じものを実装できますか?

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

delegatesToBeIncludednullの場合、何も含まれません。

https://stackoverflow.com/a/38823723/5852947 これは私が望むものと似ていますが、デリゲートの代わりに文字列を使用します。

https://stackoverflow.com/a/35889204/5852947 これも面白いです。

Entity Framework Coreでラムダ 'include'を複数のレベルで渡す方法は?これは複数のレベルに焦点を当てています(私は1つのレベルを持っています)

https://stackoverflow.com/a/52156692/5852947 これも有望です。

どちらの方向に行けばいいですか?

リビジョン1:なぜこれが必要なのですか?aa新しいオブジェクトの要素に基づいて作成されます。オブジェクトを作成するたびに、EFがDBを読み取ることに気付きました(遅延読み込みが使用されます)。わずか50ミリ秒ですが、n回繰り返されます。この関数はテンプレートクラスに実装されているため、Transactionsもパラメータです。

リビジョン2:完全なコードにはフィルタリング(正確にはページネーション)があり、最後にToList()があります。テンプレート関数に実装されているというトリッキーな部分。dbTableSelector代理人です:readonly Func<MainDbContext, DbSet<TDbTable>> dbTableSelector;

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

その後、の各要素myListを別のタイプのオブジェクトに変換します。これは、遅延読み込みが要素ごとに1つずつアクティブ化される場所です。そのため、インクルードを使用しようとしています。dbTableSelector(db)返される場合は、返さTransactionsれるときにさまざまな要素を含める必要がありますInstruments。したがって、IncludeMoreには、含めるフィールドを定義するListパラメーターが必要です。

回答

IstvanHeckl Aug 27 2020 at 08:58

これが解決策です。これに基づいています。

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

これは呼び出しです:

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