实体框架刷新数据

Mar*_*tin 7 c# entity-framework

我有一个datagrid,它有一个通过BindingSource绑定到它的集合:

            bsProducts.DataSource = cc.Products.Local.ToBindingList();
Run Code Online (Sandbox Code Playgroud)

网格中的一个实体正在以不同的形式进行编辑(并保存),我想在此表单上刷新网格,现在我尝试重新加载实体,重新加载整个本地上下文但由于某种原因它不是阅读相关的子实体.现在,当我关闭整个表格并再次打开它时,所有正在阅读.

要刷新实体,我使用以下代码:

        await cc.Entry<Product>(product).ReloadAsync();
Run Code Online (Sandbox Code Playgroud)

但是,这不会加载任何绑定到产品实体的相关实体.之后我重新尝试更新BindingSource,但没有运气.

Ger*_*old 2

我碰巧正在研究实体对象图的“访问者”。看到你的问题,我对其进行了最后的修改,使其对你的情况(以及许多其他情况)有用。它不是众所周知的访问者模式中的真正访问者,但它基本上执行相同的操作:它遍历对象图并为其遇到的每个实体执行一些操作。

\n\n

使用这种方法,您可以简单地调用...

\n\n
cc.Visit(product, e => cc.Entry(e).Reload());\n
Run Code Online (Sandbox Code Playgroud)\n\n

...您会看到product所有附着的对象都被重新加载。

\n\n

这是代码:

\n\n
public static class DbContextExtensions\n{\n    public static void Visit(this DbContext context, object entity, Action<object> action)\n    {\n        Action<object, DbContext, HashSet<object>, Action<object>> visitFunction = null; // Initialize first to enable recursive call.\n        visitFunction = (ent, contxt, hashset, act) =>\n          {\n              if (ent != null && !hashset.Contains(ent))\n              {\n                  hashset.Add(ent);\n                  act(ent);\n                  var entry = contxt.Entry(ent);\n                  if (entry != null)\n                  {\n                      foreach (var np in contxt.GetNavigationProperies(ent.GetType()))\n                      {\n                          if (np.ToEndMember.RelationshipMultiplicity < RelationshipMultiplicity.Many)\n                          {\n                              var reference = entry.Reference(np.Name);\n                              if (reference.IsLoaded)\n                              {\n                                  visitFunction(reference.CurrentValue, contxt, hashset, action);\n                              }\n                          }\n                          else\n                          {\n                              var collection = entry.Collection(np.Name);\n                              if (collection.IsLoaded)\n                              {\n                                  var sequence = collection.CurrentValue as IEnumerable;\n                                  if (sequence != null)\n                                  {\n                                      foreach (var child in sequence)\n                                      {\n                                          visitFunction(child, contxt, hashset, action);\n                                      }\n                                  }\n                              }\n                          }\n                      }\n                  }\n              }\n          };\n        visitFunction(entity, context, new HashSet<object>(), action);\n    }\n\n    // Get navigation properties of an entity type.\n    public static IEnumerable<NavigationProperty> GetNavigationProperies(this DbContext context, Type type)\n    {\n        var oc = ((IObjectContextAdapter)context).ObjectContext;\n        var objectType = ObjectContext.GetObjectType(type); // Works with proxies and original types.\n\n        var entityType = oc.MetadataWorkspace.GetItems(DataSpace.OSpace).OfType<EntityType>()\n                           .FirstOrDefault(et => et.Name == objectType .Name);\n        return entityType != null\n            ? entityType.NavigationProperties\n            : Enumerable.Empty<NavigationProperty>();\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

它是一个封装在扩展方法中的递归函数。我包装了递归部分,这样我就可以HashSet在图表中发送本地数据,收集访问过的实体,从而防止循环引用。基本上,该函数将指定的操作应用于实体,然后找到其导航属性 \xe2\x80\x93(可以是引用或集合) \xe2\x80\x93 获取它们的值 ( CurrentValue),然后调用自身来获取这些值。

\n\n

请注意,我还检查导航属性是否已加载。如果没有这个,可能会触发无休止的延迟加载链。

\n\n

另请注意,这将为图中的每个实体触发一个查询。对于大型对象图来说,这不是一个合适的方法。如果您想刷新大量数据,您应该采取不同的方法,最好创建一个新的上下文。

\n