2015-11-24 19 views
7

このフォームのグリッドをリフレッシュするように、エンティティをリロードしようとしましたが、ローカルコンテキスト全体をリロードしましたが、何らかの理由で関連するサブエンティティを読み込んでいません。今すぐフォーム全体を閉じてもう一度開くと、すべてが読み込まれています。Entity Frameworkのデータの更新

 await cc.Entry<Product>(product).ReloadAsync(); 

しかし、それは製品のエンティティにバインドされているすべての関連するエンティティをロードしません:私は次のコードを使用していたエンティティを更新するには

。私は後でBindingSourceを更新することを再試行しましたが、運はありません。

bsProducts.DataSource = cc.Products.Local.ToBindingList(); 
bsProducts.DataBind(); 

次に適用したいmigth:

+0

リロード後、もう一度バインドしますか? – MichaelMao

+0

はい、ReloadAsyncの後も、プロパティには関連する新しい関連エンティティは含まれていませんが、古いものだけが含まれています。私は関連するエンティティを手動で読み込んでList <>として割り当てることで回避策を作成しました。 – Martin

+0

更新後に 'dbProducts.DataBind()'を使用しようとしました –

答えて

2

私は、エンティティオブジェクトグラフのための「訪問者」に仕事ができることが起こりました。あなたの質問を見て、私はあなたのケース(および他の多くの場面)で役立つ最後のタッチを与えました。よく知られている訪問者パターンのように実際の訪問者ではありませんが、基本的に同じことです。オブジェクトグラフをたどり、遭遇する各エンティティに対して何らかのアクションを実行します。あなたは、単に呼び出すことができるこの方法を使用する

...

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つのクエリが発生することにも注意してください。これは、ラージオブジェクトグラフには適していません。大量のデータをリフレッシュする場合は、別の方法を採用する必要があります。新しいコンテキストを作成することをお勧めします。

2

あなたはApplyCurrentValues()関数を試してみましたあなたはすでにないリフレッシュ機能を作成した場合、それは、単に最新の値をとるisin'tあなたのコンテキストのように見えますそうする前に現在の値。

申し訳ありません申し訳ありませんがそれを解決しない場合、私は同様の問題を抱えており、これで解決しました、あなたのケースではないかもしれません。

https://msdn.microsoft.com/en-us/library/dd487246(v=vs.110).aspx

関連する問題