2015-11-24 18 views
7

ho un datagrid che ha una collezione legata ad esso attraverso un BindingSource:Entity Framework Aggiorna dati

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

Una delle entità nella griglia è in fase di modifica (e salvato) in una forma diversa e vorrei Mi piace aggiornare la griglia su questo modulo, ora ho provato a ricaricare l'entità, ricaricare l'intero contesto locale ma per qualche motivo non sta leggendo le relative sottoentità. Ora quando chiudo l'intero modulo e lo apro di nuovo tutto viene letto.

Per aggiornare l'entità sto utilizzando il seguente codice:

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

Ma questo non caricare alcuna entità collegate che sono tenuti a dell'Ente del prodotto. Ho tentato nuovamente di aggiornare BindingSource in seguito, ma senza fortuna.

+0

Dopo aver ricaricato, ti leghi di nuovo? – MichaelMao

+0

Sì, ma dopo ReloadAsync la proprietà non contiene ancora nessuna delle relative entità correlate, solo le vecchie. Ho risolto il problema caricando manualmente le entità correlate e assegnandole come elenco <>. – Martin

+0

prova ad usare 'dbProducts.DataBind()' dopo l'aggiornamento –

risposta

2

mi è capitato di essere al lavoro su un "visitatore" per un oggetto grafico entità. Vedendo la tua domanda ho dato l'ultimo tocco per renderlo utile nel tuo caso (e molti altri). Non è un visitatore reale come nel noto modello di visitatore, ma fondamentalmente la stessa cosa: attraversa un oggetto grafico ed esegue un'azione per ogni entità che incontra.

Utilizzando questo metodo si può semplicemente chiamare ...

cc.Visit(product, e => cc.Entry(e).Reload()); 

... e vedrai che product e tutti gli oggetti che aderiscono vengono ricaricati.

Ecco il codice:

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

È una funzione ricorsiva avvolto in un metodo di estensione. Ho avvolto la parte ricorsiva in modo da poter inviare uno HashSet locale sul grafico che raccoglie le entità visitate e quindi impedisce i riferimenti circolari. Fondamentalmente la funzione applica l'azione specificata all'entità, quindi trova le sue proprietà di navigazione - che possono essere riferimenti o raccolte - ottiene i loro valori (CurrentValue) e quindi chiama se stesso per questi valori.

Si noti che si verifica anche se le proprietà di navigazione sono caricate. Senza questo, una catena infinita di caricamento pigro può essere attivata.

Si noti inoltre che questa operazione genera una query per ogni entità nel grafico. Questo non è un metodo adatto per i grafici di oggetti di grandi dimensioni. Se si desidera aggiornare grandi quantità di dati, è necessario adottare un approccio diverso, preferibilmente creare un nuovo contesto.

2

Hai provato i applyCurrentValues ​​() la funzione, sembra che il tuo contesto appena isin't prendendo i valori più recenti, se già creato una funzione di aggiornamento che fa:

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

Poi si migth desidera applicare valori correnti prima di farlo.

Scusate se non è stato risolto, ho avuto un problema simile e l'ho risolto, potrebbe non essere il vostro caso.

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