Entity Framework Refresh Data
I have a datagrid that has a collection bound to it through a BindingSource:
bsProducts.DataSource = cc.Products.Local.ToBindingList();
One of the entities in the Grid is being edited (and saved) in a different form and i would like to refresh the grid on this form, now I tried to reload the entity, reload the whole local context but for some reason it is not reading the related sub entities. Now when I close the whole form and open it up again all is being read.
To refresh the entity i'm using the following code:
await cc.Entry<Product>(product).ReloadAsync();
But that will not load any related entities that are bound to the Product Entity. I have retried to update the BindingSource afterwards but no luck.
I happened to be working on a "visitor" for an entity object graph. Seeing your question I gave it the last touch to make it useful in your case (and many others). It's not a real visitor as in the well-known visitor pattern, but it does basically the same thing: it traverses an object graph and executes some action for each entity it encounters.
Using this method you can simply call ...
cc.Visit(product, e => cc.Entry(e).Reload());
... and you'll see that product
and all adhering 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>();
}
}
It is a recursive function wrapped in an extension method. I wrapped the recursive part so I could send a local HashSet
down the graph that collects visited entities and thereby prevents circular references. Basically the function applies the specified action to the entity, then finds its navigation properties – which can be references or collections – gets their values ( CurrentValue
) and then calls itself for these values.
Notice that I also check if the navigation properties are loaded. Without this, an endless chain of lazy loading may get triggered.
Also notice that this fires one query for each entity in the graph. This is not a suitable method for large object graphs. If you want to refresh large amounts of data you should take a different approach, preferably create a new context.
Have you tried the ApplyCurrentValues() function, it looks like your context just isin't taking the newest values, if you already created a refresh function that does :
bsProducts.DataSource = cc.Products.Local.ToBindingList();
bsProducts.DataBind();
Then you migth want to apply current values before doing so.
Sorry if it dosen't solve it, i had a similar problem and solved it with this, might not be your case.
https://msdn.microsoft.com/en-us/library/dd487246(v=vs.110).aspx
链接地址: http://www.djcxy.com/p/88950.html上一篇: 如何为bitbucket存储库创建数字对象标识符(DOI)?
下一篇: 实体框架刷新数据