私は、エンティティオブジェクトグラフのための「訪問者」に仕事ができることが起こりました。あなたの質問を見て、私はあなたのケース(および他の多くの場面)で役立つ最後のタッチを与えました。よく知られている訪問者パターンのように実際の訪問者ではありませんが、基本的に同じことです。オブジェクトグラフをたどり、遭遇する各エンティティに対して何らかのアクションを実行します。あなたは、単に呼び出すことができるこの方法を使用する
...
cc.Visit(product, e => cc.Entry(e).Reload());
...そして、あなたはproduct
と、すべての付着したオブジェクトが再ロードされていることがわかります。ここで
はコードです:
public static class DbContextExtensions
{
public static void Visit(this DbContext context, object entity, Action<object> action)
{
Action<object, DbContext, HashSet<object>, Action<object>> visitFunction = null; // Initialize first to enable recursive call.
visitFunction = (ent, contxt, hashset, act) =>
{
if (ent != null && !hashset.Contains(ent))
{
hashset.Add(ent);
act(ent);
var entry = contxt.Entry(ent);
if (entry != null)
{
foreach (var np in contxt.GetNavigationProperies(ent.GetType()))
{
if (np.ToEndMember.RelationshipMultiplicity < RelationshipMultiplicity.Many)
{
var reference = entry.Reference(np.Name);
if (reference.IsLoaded)
{
visitFunction(reference.CurrentValue, contxt, hashset, action);
}
}
else
{
var collection = entry.Collection(np.Name);
if (collection.IsLoaded)
{
var sequence = collection.CurrentValue as IEnumerable;
if (sequence != null)
{
foreach (var child in sequence)
{
visitFunction(child, contxt, hashset, action);
}
}
}
}
}
}
}
};
visitFunction(entity, context, new HashSet<object>(), action);
}
// Get navigation properties of an entity type.
public static IEnumerable<NavigationProperty> GetNavigationProperies(this DbContext context, Type type)
{
var oc = ((IObjectContextAdapter)context).ObjectContext;
var objectType = ObjectContext.GetObjectType(type); // Works with proxies and original types.
var entityType = oc.MetadataWorkspace.GetItems(DataSpace.OSpace).OfType<EntityType>()
.FirstOrDefault(et => et.Name == objectType .Name);
return entityType != null
? entityType.NavigationProperties
: Enumerable.Empty<NavigationProperty>();
}
}
それは、拡張メソッドに包まれた再帰関数です。私は再帰的な部分をラップしたので、ローカルのHashSet
を訪問先のエンティティを収集して循環参照を防止するグラフに送ることができました。基本的に、この関数はエンティティに指定されたアクションを適用し、その参照プロパティまたはコレクションである可能性のあるナビゲーションプロパティを見つけ、その値(CurrentValue
)を取得してこれらの値を呼び出します。
ナビゲーションプロパティが読み込まれているかどうかを確認します。これがなければ、無限の遅延読み込みが発生する可能性があります。
グラフの各エンティティに対して1つのクエリが発生することにも注意してください。これは、ラージオブジェクトグラフには適していません。大量のデータをリフレッシュする場合は、別の方法を採用する必要があります。新しいコンテキストを作成することをお勧めします。
リロード後、もう一度バインドしますか? – MichaelMao
はい、ReloadAsyncの後も、プロパティには関連する新しい関連エンティティは含まれていませんが、古いものだけが含まれています。私は関連するエンティティを手動で読み込んでList <>として割り当てることで回避策を作成しました。 – Martin
更新後に 'dbProducts.DataBind()'を使用しようとしました –