Entity Framework Data Updates

I have a datagrid that has a collection associated with it through a BindingSource:

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

One of the objects in the Grid is edited (and saved) in a different form, and I would like to update the grid in this form, now I tried to reload the object, reload the entire local context, but for some reason it does not read related entities. Now, when I close the whole form and open it again, everything is read.

To update the object, I use the following code:

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

But this will not load related objects bound to the Product object. I tried updating the BindingSource again, but no luck.

+7
c # entity-framework
source share
2 answers

I happened to work on a "visitor" for the graph of objects of the object. When I saw your question, I gave him the final touch to make it useful in your case (and many others). This is not a real visitor, as in the well-known visitor template, but he does basically the same thing: he crosses the graph of objects and performs some action for every entity he encounters.

Using this method, you can simply call ...

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

... and you will see that product and all adhesive objects are reloaded.

Here is the code:

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

This is a recursive function wrapped in an extension method. I wrapped the recursive part so that I can send a local HashSet on a schedule that collects visited objects and thereby prevents circular references. Basically, a function applies the specified action to an entity, and then finds that its navigation properties, which can be links or collections, get their values ​​( CurrentValue ), and then calls themselves for these values.

Please note that I also check if the navigation properties are loaded. Without this, an endless chain of lazy loading can begin.

Also note that this raises one query for each object in the graph. This is not suitable for large object graphs. If you want to update large amounts of data, you should use a different approach, it is preferable to create a new context.

+2
source share

You tried the ApplyCurrentValues ​​() function, it looks like your context just doesn't accept the newest values ​​if you already created an update function that does:

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

You will then blink to apply the current values ​​before.

Sorry, if he doesn’t solve it, I had a similar problem, and I decided to do it, maybe this is not your case.

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

+2
source share

All Articles