2009-12-22 2 views
5

Wir schreiben eine WPF-Anwendung mit Entity-Framework (Silverlight mit RIA-Services, um genau zu sein). Wir verwenden einen gemeinsamen ObjectContext über die Anwendung, sodass wir von der gemeinsamen Nutzung von Daten in den Modulen profitieren können.Entity Framework ObjectContext in Windows/WPF/Silverlight-Anwendung

Das Problem ist - wenn Benutzer während seiner Arbeit geöffnet wird sagen wir historische Verkäufe, wird es in den ObjectContext geladen und bleibt dort bis zum Ende der Anwendung. Also sollte ein anderes Muster verwendet werden.

Ich weiß, dass ObjectContexts als einzelne Unit-of-Work verwendet werden sollte. Aber wie können Sie anderen Teilen der Anwendung mitteilen, dass sich etwas geändert hat und sie ihre Daten neu laden sollten?

Edit: Ok, EventAggregator, aber dann würde dies dazu führen, dass alle anderen Teile ihre (wahrscheinlich viel davon doppelt) Daten neu laden. Wahrscheinlich werden auch viele Ereignisse für alle Arten von Gruppen benötigt.

Wie lösen Sie diese Probleme? Meine aktuelle Lösung ist eine Art Kompromiss: Verwenden Sie einen gemeinsamen ObjectContext für die Kerndaten, die von der gesamten Anwendung verwendet werden, damit sie automatisch freigegeben und aktualisiert werden können. Und für die große Menge an Daten, verwenden Sie einen neuen separaten ObjectContext. Irgendwelche besseren Ideen?

Gibt es eine Möglichkeit, Entitäten aus ihrem DataContext "freizugeben", damit der Garbage Collector seine Arbeit erledigen und den Speicher freigeben kann?

Antwort

2

Warten Sie, ist es WPF oder Silverlight? In diesem Fall sind sie sehr unterschiedlich und meine Antwort wäre anders.

WPF Lösung

In WPF würde ich eine einzige Object pro Formular erstellen. Auf diese Weise dauert der Kontext nur so lange wie das Formular selbst. Sie sollten dann ein Ereignissystem implementieren, damit beim Speichern von Änderungen an einer Entität die anderen Formulare, die sie möglicherweise zum Aktualisieren ihrer Daten benötigen, benachrichtigt werden können (z. B. INotifyPropertyChanged). Oren Eini wrote a pretty good article on this architecture using NHibernate in MSDN magazine. Sie sollten in der Lage sein, das Architekturkonzept von seinem Artikel zu bekommen.

Silverlight-Lösung

Nun ist Silverlight anders. Silverlight ermöglicht Ihnen im Wesentlichen nur ein Formular in Ihrer Anwendung. Ja, es gibt einige Tricks, die Sie tun können, um das Root-Visual des Formulars zu verschiedenen "Seiten" zu navigieren, aber es ist immer noch nur ein Formular und der Benutzer kann nicht mehrere Fenster in einem Silverlight RIA öffnen. Aus diesem Grund würde ich einen .Net RIA Services ObjectContext pro Silverlight RIA Instanz machen. Denken Sie daran, dass es sich bei RIA Services nicht um eine tatsächliche Verbindung zu Ihrer Datenbank handelt, sondern lediglich um ein Caching- und Änderungsverfolgungsobjekt, das mit einem Webdienst verknüpft ist. Es ist daher durchaus akzeptabel, dieses Objekt für längere Zeit bestehen zu lassen, da es keine Serverressourcen bindet. Wenn Ihr Silverlight RIA mehrere Browserfenster öffnet oder mehr als ein Silverlight-Objekt hat, sollten Sie einen ObjectContext pro Silverlight-Instanz haben.

Auf dem Server verwenden Sie ein Entity Framework ObjectContext im Web-Service und es sollte nur für die Dauer einer Anfrage leben. Je zustandsloser Sie Ihre Dienste leisten können, desto skalierbarer und performanter werden sie. Sie möchten Ihren EF ObjectContext öffnen, verwenden und so bald wie möglich schließen.


EDIT:

Wenn alles, was Sie tun wünschen ist ein Objekt aus dem Objektkontext zu lösen, dann können Sie nur die Verwendung context.Detach(entity) Methode. Sie können eine example of how to do this on MSDN finden.

+0

Mit dieser Anwendung sprechen wir über Silverlight. Mit Prism/Caliburn glaube ich, dass es kein Problem ist, einen einzelnen ObjectContext pro Sicht (Modul?) Zu haben. Auch hier ist das Problem, wenn viele Daten auf den Client geladen werden sollen. Soweit ich jetzt bin, wäre die beste Lösung, einen gemeinsamen ObjectContext für grundlegende Entitäten zu erstellen, die durch die gesamte Anwendung verwendet werden, so dass diese automatisch synchronisiert werden, und separate ObjectContexts zum Laden großer Datenmengen in z. einige historische Berichte. – gius

+0

Ich würde nicht versuchen, wirklich große Datenblöcke an den Client zu senden. Stattdessen würde ich auf dem Server filtern und nur die Ergebnisse zurückgeben, die der Client in diesem Moment sehen möchte. Menschen können 100.000 Datensätze nicht lesen, also senden Sie diese nicht an einen Menschen. Lassen Sie das Problem stattdessen eine Suche/Filter und senden Sie die Ergebnisse nur an den Client. Wenn Sie Berichte erstellen, erstellen Sie die zusammengefassten Übersichtsdaten auf dem Server. Zum Beispiel wäre es besser, das monatliche Umsatzvolumen auf dem Server zu berechnen und eine einzelne Zahl an den Kunden zu senden, als an 5000 Verkaufsdatensätze. –

+0

Das stimmt, aber wenn der Benutzer während der Anwendungslebenszeit, sagen wir mal, die Seiten 1, 10, 20 sieht, sind diese Daten immer noch im Speicher. Auf der anderen Seite könnte die Verwendung eines separaten ObjectContext- und Daten-Paging das Problem der großen Daten, die im Arbeitsspeicher bleiben, lösen. – gius

1

Sie könnten Repository-Muster verwenden. Eine zusätzliche Abstraktionsebene zwischen UI und DAL.

Machen Sie Datensammlungen im Repository statisch und beobachtbar. Wenn das Repository eines von ihnen aktualisiert, sollte die UI-Schicht aufholen. Nur eine Idee.

+0

Das ist mein Problem nicht lösen - die Sammlungen auf dem Client bleiben würden, so, wenn es zum Beispiel ist 1GB Daten in der Datenbank, früher oder später wird es auch auf dem Client geladen werden. Auf der anderen Seite könnte dies eine mögliche Lösung zeigen. Danke für die Idee! – gius

0

Verwenden Sie ObservableCollections im ObjectContext. Verwenden Sie ein Ereignis, das bei NotifyPropertyChange ausgelöst wird. Verwenden Sie ein Publish/Subscribe-Muster zwischen den Ansichtsmodellen, um sie über die Änderung zu informieren, und verwenden Sie dies, um die anderen Ansichten zu aktualisieren.

+1

Alle von der EF erstellten Sammlungen sind ObservableCollection und Entitäten verwenden NotifyPropertyChanged. Das Problem ist, dass ich nicht nur ObjectContext während des gesamten Anwendungslebenszyklus verwenden kann, weil dann keine Daten aus dem Speicher freigegeben werden, sobald sie in die Anwendung geladen sind. Auf der anderen Seite führt die Verwendung von separatem ObjectContext für jede einzelne Aktion zu Problemen beim Aktualisieren von Daten - dieselben Daten werden mehrmals von vielen Orten geladen, und die Synchronisierung würde benutzerdefinierte Ereignisse für jede Art von Daten bedeuten. Die Hauptfrage ist, ob es ein Framework/Muster für dieses Problem gibt. – gius

Verwandte Themen