在Windows/WPF/Silverlight应用中的实体框架ObjectContext

5
我们正在使用Entity Framework编写一个WPF应用程序(确切地说是使用Silverlight和RIA服务)。我们通过整个应用程序使用共享的ObjectContext,以便我们可以从模块间共享数据。
问题在于-如果用户在工作期间打开了历史销售记录,它会加载到ObjectContext中,并一直保留到应用程序结束。因此,应该使用另一种模式。
我知道ObjectContext应该用作单个工作单元。但是,那么如何让应用程序的其他部分知道某些内容已更改,他们应该重新加载其数据?
编辑:好吧,EventAggregator,但是,这将导致所有其他部分重新加载它们的(可能大部分重复)数据。还可能需要许多事件来处理所有类型的实体组。
你如何解决这些问题?我的当前解决方案是一种妥协-对于整个应用程序使用共享的ObjectContext,以便可以自动共享和更新核心数据。对于大量数据,请使用新的单独ObjectContext。有更好的想法吗?
是否有一种方法可以“释放”实体的DataContext,以便垃圾收集器可以完成其工作并释放内存?
4个回答

2
“等等,是WPF还是Silverlight?在这种情况下,它们非常不同,我的答案也会不同。”
“WPF解决方案:我会为每个窗体创建一个单独的ObjectContext。这样,上下文只会持续与窗体本身一样长的时间。然后,您应该实现一个事件系统,以便在保存实体更改时,您可以通知其他窗体可能需要刷新其数据(例如 INotifyPropertyChanged)。 Oren Eini在MSDN杂志上写了一篇非常好的文章,介绍了使用NHibernate的这种架构。您应该能够从他的文章中获得架构概念。”
“Silverlight解决方案:”
现在,Silverlight有所不同。Silverlight基本上只允许您在应用程序中拥有一个表单。是的,您可以使用一些技巧将表单的根可视元素导航到不同的“页面”,但仍然只有一个表单,用户无法在一个Silverlight RIA中打开多个窗口。因此,我会为每个Silverlight RIA实例创建一个.Net RIA服务ObjectContext。请记住,RIA服务并不是与数据库的实际连接,它只是与Web服务链接的缓存和更改跟踪对象。因此,将这个对象保留在长时间存在状态是完全可以接受的,因为它不会占用任何服务器资源。如果您的Silverlight RIA打开多个浏览器窗口或具有多个Silverlight对象,则应为每个Silverlight实例提供一个ObjectContext。
在服务器上,您可以在Web服务中使用Entity Framework ObjectContext,并且它只能存在于一个请求的持续时间内。您可以使您的服务尽可能无状态,这样它们就更具可扩展性和性能。您希望尽快打开EF ObjectContext,使用它,并立即关闭它。

编辑:

如果你想要做的只是将一个对象从对象上下文中分离出来,那么你可以使用 context.Detach(entity) 方法。你可以在 MSDN 上找到一个 如何执行此操作的示例


使用这个应用程序,我们正在谈论Silverlight。使用Prism/Caliburn,我认为每个视图(模块?)只有一个ObjectContext不是问题。再次强调的问题是,如果需要加载大量数据到客户端,该怎么办? 就我目前而言,最好的解决方案是创建一个共享的ObjectContext,用于整个应用程序中使用的基本实体,以便自动同步这些内容,并为加载大量数据的情况创建单独的ObjectContext,例如某些历史报告。 - gius
我不会尝试将非常大的数据块发送给客户端。相反,我会在服务器上进行过滤,并仅返回客户端在那一时刻想要看到的结果。人类无法阅读10万条记录,因此不要向人类发送那么多记录。相反,让用户发出搜索/筛选,并仅向客户端发送结果。如果您正在创建报告,请在服务器上创建聚合摘要数据。例如,最好在服务器上计算每月销售额并向客户端发送一个数字,而不是发送5000个销售记录。 - Mark Ewer
没错,但是如果用户在应用程序的生命周期中任何时候看到了第1页、第10页、第20页,那么这些数据仍然会留在内存中。 另一方面,使用单独的ObjectContext和数据分页可以解决大数据留在内存中的问题。 - gius

1
您可以使用仓储模式(Repository Pattern),在 UI 层和数据访问层(DAL)之间添加一个额外的抽象层。
将仓储中的数据集合设置为静态和可观测的,这样每当仓储更新其中任何一个集合时,UI 层就会跟上。这只是一个想法。

这并没有解决我的问题 - 集合仍然会留在客户端,因此如果数据库中有1GB的数据,迟早也会加载到客户端。另一方面,这可能显示出一个可能的解决方案。感谢您的想法! - gius

0

在 ObjectContext 中使用 ObservableCollections。使用在 NotifyPropertyChange 上触发的事件。在视图模型之间使用发布/订阅模式通知它们更改并使用此来更新其他视图。


1
EF创建的所有集合都是ObservableCollection,并且实体使用NotifyPropertyChanged。问题在于我不能只在整个应用程序生命周期内仅使用ObjectContext,因为一旦它们加载到应用程序中,就没有数据会释放出来。另一方面,为每个单独的操作使用单独的ObjectContext将导致刷新数据的问题 - 相同的数据将从多个地方多次加载,并且同步意味着每种类型的数据都需要自定义事件。主要问题是是否有任何框架/模式可以解决这个问题。 - gius

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接