私はEF7(CORE)を使い始めたばかりで、次のことを正しく実装するのに苦労しています。私は孫のテーブルを持っている複数の子テーブルを持つテーブルを持っているとしましょう(これらは順番に外部キーテーブルを持っています)。私はすべてのものへのアクセスを望んでいた場合、私は今、私は私の子テーブルのすべてが含まれるように含まれています...が、私はそれが舞台裏発射SQLを見てチェーン化の必要性を理解し、このエンティティフレームワーク7複数レベルの子テーブル
TABLE_A.Include(c => c.TABLE_B).ThenInclude(co => co.TABLE_C)
.ThenInclude(coi => coi.TABLE_D)
.ThenInclude(coia => coia.TABLE_E)
.Include(c => c.TABLE_B).ThenInclude(co => co.TABLE_F)
.ThenInclude(coa => coa.TABLE_G)
.ThenInclude(coaAcc => coaAcc.TABLE_H)
.ThenInclude(coaAccInt => coaAccInt.TABLE_D)
.ThenInclude(coaAccIntAgent => coaAccIntAgent.TABLE_E)
ようなものが必要だろう11のSQL文を実行しています。これはひどく非効率的です。
これを行うには、これが最善の方法ですか?私は今、TABLE_Bに3つ以上の子テーブルを追加する新しい要件を受けました。もっと多くのインクルードが必要になります。
私がやっていることの背後にある論理を理解しています。遅延読み込みは現在EF7ではサポートされていませんが、これは非常に効率的な方法です。一度にやります。
このようなことにはベストプラクティスがありますか?EF7を使用して必要なことを行う方法については把握していませんか?
ご迷惑をおかけして申し訳ございません。 、あなたはナビゲーションの各プロパティを必要なときに、その後
public static void Load<TSource, TDestination>(this EntityEntry<TSource> entry, Expression<Func<TSource, IEnumerable<TDestination>>> path, Expression<Func<TDestination, TSource>> pathBack = null) where TSource : class where TDestination : class
{
var entity = entry.Entity;
var context = entry.Context;
var entityType = context.Model.FindEntityType(typeof(TSource));
var keys = entityType.GetKeys();
var keyValues = context.GetEntityKey(entity);
var query = context.Set<TDestination>() as IQueryable<TDestination>;
var parameter = Expression.Parameter(typeof(TDestination), "x");
PropertyInfo foreignKeyProperty = null;
if (pathBack == null)
{
foreignKeyProperty = typeof(TDestination).GetProperties().Single(p => p.PropertyType == typeof(TSource));
}
else
{
foreignKeyProperty = (pathBack.Body as MemberExpression).Member as PropertyInfo;
}
var i = 0;
foreach (var property in keys.SelectMany(x => x.Properties))
{
var keyValue = keyValues[i];
var expression = Expression.Lambda(
Expression.Equal(
Expression.Property(Expression.Property(parameter, foreignKeyProperty.Name), property.Name),
Expression.Constant(keyValue)),
parameter) as Expression<Func<TDestination, bool>>;
query = query.Where(expression);
i++;
}
var list = query.ToList();
var prop = (path.Body as MemberExpression).Member as PropertyInfo;
prop.SetValue(entity, list);
}
public static object[] GetEntityKey<T>(this DbContext context, T entity) where T : class
{
var state = context.Entry(entity);
var metadata = state.Metadata;
var key = metadata.FindPrimaryKey();
var props = key.Properties.ToArray();
return props.Select(x => x.GetGetter().GetClrValue(entity)).ToArray();
}
:
おかげ
これはどのようにコレクションに使用できますか? TABLE_Aはコレクションです...各エンティティにTABLE_Bのリストがあります。 。私は '_context.Entry(<表のリストA>)をロード(。B => B)を使用した場合;' 私はエラー が 'のIQueryable ' TABLE_B」の定義が含まれていません取得します'拡張メソッド' TABLE_B '型' IQueryable 'の最初の引数を受け入れることはできませんでした –
rborob
_context.Entry単一のオブジェクトを取得し、最初にすべてのTABLE_Aリストをロードし、TABLE_Aリスト内の項目ごとに必要なときはいつでも、 :var item = TABLE_A.First(); <実際には、LazyLoadiningに似ていますが、明示的なロードナビゲーションに似ています。 –
うわー、それはひどい解決策です。ビュー内でアイテム300個をレンダリングし、10個のFKテーブルからデータを表示すると、3000個のクエリが効果的に実行されます。 – rborob