实体框架 4.1 DbSet 重新加载
Posted
技术标签:
【中文标题】实体框架 4.1 DbSet 重新加载【英文标题】:Entity Framework 4.1 DbSet Reload 【发布时间】:2011-08-13 13:44:27 【问题描述】:我正在使用 DbContext
场景的单个实例在 WPF 应用程序中本地隐藏整个数据库副本。我听说这是不好的做法,但我的数据库很小,并且在应用程序运行时我需要在本地获得完整的副本。
IQueryable
、Load()
的扩展方法让我可以预加载DbSet<>
的元素,这样我就可以将事物绑定到DbSet<>
的Local 属性。数据库中的数据变化很快,所以我想SaveChanges()
并重新加载一切,甚至是已经跟踪的对象。再次调用Load()
方法不会更新已跟踪但未标记为已更改的项目。
在DbSet<>
中重新加载预加载项的首选方法是什么?在我的脑海中,我只能想到调用SaveChanges()
,然后遍历所有条目并将跟踪值和原始值设置为数据库中的当前值,然后Load()
可能已添加的任何新对象。在我的场景中,不可能删除对象,但从长远来看,我可能必须支持项目删除。这似乎不对,应该有一种方法可以删除所有内容并重新加载。似乎放弃我的上下文并重新开始更容易,但是 WPF 中的所有元素都已经绑定到Local´ObservableCollection<>
,这只会弄乱界面。
【问题讨论】:
【参考方案1】:这不是您应该使用DbContext
的方式,因此几乎不可能重新加载数据。长时间保持单一上下文是incorrect usage。该链接还将回答您跟踪的实体未更新的原因。
您可以通过在DbEntityEntry
上调用Reload
来选择性地重新加载单个实体:
context.Entry(entity).Reload();
您还可以恢复为ObjectContext
并将ObjectQuery
与MergeOption.OverrideChanges
一起使用,或者将Refresh
与RefreshMode.StoreWins
一起用于实体集合。
所有这些方法都存在一些问题:
如果记录在数据库中被删除,它不会从上下文中删除。 关系的变化并不总是被刷新。获取新数据的唯一正确方法是Dispose
上下文,创建一个新的并从头开始加载所有内容 - 无论如何你都在这样做。
【讨论】:
感谢您的回复,但我有点迷茫,因为我已经读到在我的场景中首选完全相反的情况。我会回顾这些主题,然后回来。 我不会在关系中发生任何变化,也不会在数据库中删除。我将在今天晚些时候开始另一个问题,并尝试解释为什么我不能拥有一个短暂的 DbContext。我真的希望你能提供一些有价值的意见。【参考方案2】:在 Entity Framework 4.1 中,WPF 数据绑定的建议已更改为使用 .Local 和持久 DbContext。
http://blogs.msdn.com/b/efdesign/archive/2010/09/08/data-binding-with-dbcontext.aspx
当然,您可以在需要时将其丢弃,但如果您这样做,可能会对 UI 产生负面影响。
这是另一种方法,但我不确定它是否考虑了 EF4.1 的功能:
http://msdn.microsoft.com/en-us/library/cc716735.aspx
【讨论】:
非常感谢,我对整个 .Local 的事情感到非常困惑。每个人和他们的狗都告诉我不要出于任何原因使用单个 DbContext,但它清楚地为长期绑定提供了这个 .Local 属性。 @Gleno 我完全同意你的看法,恕我直言,大多数人将它用于上下文短暂的 ASP,但对于桌面应用程序,重新加载您输入新表单的所有内容只是无稽之谈,特别是如果信息通过各种形式的应用共享。【参考方案3】:DbContexts 应该存在很短的时间, 在保存更改后考虑处理它并从头开始重新加载。 有 2 组对象.. 一组来自 db,另一组用于绑定。
【讨论】:
我真的不能这样做,因为那样我会在进度中丢失 UI 状态。我真的希望我能拥有一个短暂的 DbContext,但我看不出在我的场景中它是如何实现的。【参考方案4】:请使用 using() 进行 CRUD。它会自动重新加载更新的数据。
using (myDbContext context = new myDbContext())
最好的问候, 提丁乌
【讨论】:
以上是关于实体框架 4.1 DbSet 重新加载的主要内容,如果未能解决你的问题,请参考以下文章