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,但没有运气.
我碰巧正在研究实体对象图的“访问者”。看到你的问题,我对其进行了最后的修改,使其对你的情况(以及许多其他情况)有用。它不是众所周知的访问者模式中的真正访问者,但它基本上执行相同的操作:它遍历对象图并为其遇到的每个实体执行一些操作。
\n\n使用这种方法,您可以简单地调用...
\n\ncc.Visit(product, e => cc.Entry(e).Reload());\n
Run Code Online (Sandbox Code Playgroud)\n\n...您会看到product
所有附着的对象都被重新加载。
这是代码:
\n\npublic 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