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

问题描述:

我们正在编写一个使用实体框架(具有RIA服务的Silverlight精确)的WPF应用程序。我们通过应用程序使用共享的ObjectContext,以便我们可以通过模块共享数据获益。Windows/WPF/Silverlight应用程序中的实体框架ObjectContext

问题是 - 如果用户在工作期间打开让我们说历史销售,它将被加载到ObjectContext并保持到应用程序结束。所以应该使用另一种模式。

我知道ObjectContexts应该用作单个工作单元。但是,那么,您如何让应用程序的其他部分知道某些内容已更改,并且应该重新加载其数据?

编辑:好吧,EventAggregator,但是,然后,这将导致所有其他部分重新加载它们(可能大部分是重复的)数据。所有类型的企业集团也可能需要许多事件。

你如何解决这些问题?我目前的解决方案是一种妥协 - 为共享应用程序使用的核心数据使用共享的ObjectContext,以便它们可以自动共享和更新。对于大量的数据,使用一个新的单独的ObjectContext。任何更好的想法?

有没有办法如何从他们的DataContext中“释放”实体,以便垃圾收集器可以完成它的工作并释放内存?

等一下,是WPF还是Silverlight?在这种情况下,他们是非常不同的,我的答案会有所不同。

WPF解决方案

在WPF中我会创建每个表单单一的ObjectContext。这样,上下文将只持续与表单本身一样长。然后,您应该实施一个事件系统,以便在保存对实体的更改时,可以提醒其他表单可能需要刷新其数据(例如,INotifyPropertyChanged)。 Oren Eini wrote a pretty good article on this architecture using NHibernate in MSDN magazine。你应该能够从他的文章中获得建筑理念。

Silverlight的解决方案

现在,Silverlight是不同的。 Silverlight实质上只允许你在你的应用程序中拥有一个表单。是的,您可以使用一些技巧将表单的根视觉导航到不同的“页面”,但它仍然只有一种形式,并且用户无法在一个Silverlight RIA中打开多个窗口。因此,我会为每个Silverlight RIA实例制作一个.Net RIA Services ObjectContext。请记住,RIA服务并不是与数据库的实际连接,它只是一个链接到Web服务的缓存和更改跟踪对象。因此,将这个对象留在更长的时间段是完全可以接受的,因为它并不占用任何服务器资源。如果您的Silverlight RIA打开多个浏览器窗口或具有多个Silverlight对象,那么您应该为每个Silverlight实例创建一个ObjectContext。

在服务器上,您在Web服务中使用了一个实体框架ObjectContext,它应该只在一个请求期间生存。您可以提供更多的无状态服务,他们将具有更高的可扩展性和高性能。你想打开你的EF ObjectContext,使用它,并尽快关闭它。


编辑:

如果所有你想要做的是从对象上下文分离的对象,那么你可以使用context.Detach(entity)方法。你可以找到一个example of how to do this on MSDN

+0

有了这个应用程序,我们正在讨论Silverlight。使用Prism/Caliburn,我认为每个视图(模块?)都有一个ObjectContext是没有问题的。同样,如果有很多数据要加载到客户端,问题是什么? 就我而言,最好的解决方案是为通过整个应用程序使用的基本实体创建一个共享的ObjectContext,以便它们自动同步,并分离ObjectContexts以加载大量数据。一些历史报道。 – gius 2010-01-03 23:06:52

+0

我不会尝试发送真正的大块数据给客户端。相反,我会在服务器上进行过滤,并只返回客户希望在那一刻看到的结果。人类无法读取100,000条记录,因此不要将这么多记录发送给人类。相反,让问题成为搜索/过滤器,并只将结果发送给客户端。如果您正在构建报告,请在服务器上创建汇总汇总数据。例如,计算服务器上的每月销售量并向客户端发送单个数字比查看5000条销售记录更好。 – 2010-01-04 18:03:59

+0

的确如此,但如果用户在应用程序生命周期中的任何时候都能看到,比如说第1,10,20页,那么这些数据仍将存储在内存中。另一方面,使用单独的ObjectContext和数据分页可以解决大数据驻留内存问题。 – gius 2010-01-04 19:03:10

您可以使用存储库模式。 UI和DAL之间的另一层抽象。

使存储库中的数据收集为静态和可观察的。然后,无论何时更新其中的任何一个,UI层都应该赶上。启发一个想法。

+0

这不解决我的问题 - 集合会留在客户端上,所以如果有例如数据库中的1GB数据迟早会加载到客户端上。另一方面,这可能会显示一个可能的解决方案。感谢您的想法! – gius 2009-12-22 22:40:43

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

+1

EF创建的所有集合都是ObservableCollection,实体使用NotifyPropertyChanged。问题是我不能在整个应用程序生命周期中只使用ObjectContext,因为一旦将它们加载到应用程序中,就不会从内存中释放数据。 另一方面,对每个单独的操作使用单独的ObjectContext会导致刷新数据时出现问题 - 相同的数据将从多个位置加载多次,并且同步将意味着每种数据的自定义事件。 主要问题是有什么框架/模式解决这个问题。 – gius 2010-01-03 22:58:37

在我们的案例中,我们决定实现一个工厂模式并在需要时实例化一个新的对象上下文(有时它不会将一对一映射到一个虚拟机)。

Agreat文章关于对象上下文续航时间: http://www.silverlightshow.net/items/Silverlight-WCF-RIA-Services-strategies-for-handling-your-Domain-Context-part-one.aspx