且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2022-11-05 09:47:37

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



WPF解决方案



在WPF中,我将为每个表单创建一个ObjectContext 。这样,上下文只会持续一段时间,只要表单本身。然后,您应该实施一个事件系统,以便在将更改保存到实体时,可以提醒他们刷新数据所需的其他表单( INotifyPropertyChanged ,例如)。 Oren Eini在MSDN杂志中使用NHibernate撰写了一篇关于此架构的相当不错的文章。。您应该可以从他的文章中获得架构概念。



Silverlight解决方案



现在,Silverlight是不同的。 Silverlight本质上只允许你在你的应用程序中有一个表单。是的,你可以做一些技巧来将窗体的根视图导航到不同的页面,但它仍然只是一种窗体,用户无法在一个Silverlight RIA中打开多个窗口。因此,我将为每个Silverlight RIA实例制作一个.Net RIA Services ObjectContext 。请记住,RIA服务不是与数据库的实际连接,它只是连接到Web服务的缓存和更改跟踪对象。因此,绝对可以将此对象存在于较长的时间段内,因为它并不捆绑任何服务器资源。如果您的Silverlight RIA打开多个浏览器窗口或有多个Silverlight对象,那么您应该每个Silverlight实例有一个ObjectContext。



在服务器上,您可以在Web服务中使用 Entity Framework ObjectContext,并且只应在一个请求的持续时间内生活。可以使您的服务更无国籍,更具有扩展性和更高的性能。你想打开你的EF ObjectContext,使用它,并尽快关闭它。






编辑:



如果您想要做的是将对象从对象上下文中分离出来,则可以使用 context.Detach(entity)方法。您可以找到如何做到这一点的例子在MSDN上


We are writing a WPF application using Entity framework (Silverlight with RIA services to be precise). We're using a shared ObjectContext through the application so that we can benefit from sharing data across the modules.

The problem is - if user during his work opens let's say historical sales, it gets loaded to the ObjectContext and stays there until the end of the application. So another pattern should be used.

I know that ObjectContexts should be used as single Unit-of-Work. But then, how do you let other parts of the application know that something has changed and they should reload their data?

Edit: Ok, EventAggregator, but then, this would cause all other parts to reload their (probably much of it duplicate) data. Also probably many event would be needed for all the types of entites groups.

How do you solve these problems? My current solution is a kind of compromise - use a shared ObjectContext for the core data used by whole appliaction so that they can be shared and updated automatically. And for the large amount of data, use a new separate ObjectContext. Any better ideas?

Is there a way how to "release" entities from their DataContext so that Garbage collector can do its job and release the memory?

Wait, is it WPF or Silverlight? In this case, they are very different and my answer would be different.

WPF Solution

In WPF I would create a single ObjectContext per form. This way, the context will only last as long as the form itself. You should then implement an event system so that when you save changes to an entity you can alert the other forms that they may need to refresh their data (INotifyPropertyChanged, for example). Oren Eini wrote a pretty good article on this architecture using NHibernate in MSDN magazine. You should be able to get the architecture concept from his article.

Silverlight Solution

Now, Silverlight is different. Silverlight essentially only allows you to have one form in your application. Yes, there are some tricks you can do to navigate the root visual of the form to different "pages" but it is still only one form and the user can't open multiple windows in one Silverlight RIA. Because of this, I would make one .Net RIA Services ObjectContext per Silverlight RIA instance. Remember, RIA Services is not an actual connection to your database, it is just a caching and change tracking object linked to a web service. So, it is perfectly acceptable to leave this object in existance for longer periods of time because it is not tying up any server resources. If your Silverlight RIA opens multiple browser windows or has more than one Silverlight object, then you should have one ObjectContext per Silverlight instance.

On the server, you use an Entity Framework ObjectContext in the web service and it should only live for the duration of one request. The more stateless you can make your services, the more scalable and performant they will be. You want to open your EF ObjectContext, use it, and close it as soon as possible.


EDIT:

If all you are wanting to do is detach an object from the object context, then you can just use the context.Detach(entity) method. You can find an example of how to do this on MSDN.