2009-12-22 4 views
5

Nous sommes en train d'écrire une application WPF en utilisant le framework Entity (Silverlight avec les services RIA pour être précis). Nous utilisons un ObjectContext partagé à travers l'application pour que nous puissions bénéficier du partage de données entre les modules. Le problème est le suivant: si l'utilisateur ouvre son travail, disons les ventes historiques, il est chargé dans ObjectContext et y reste jusqu'à la fin de l'application. Donc, un autre modèle devrait être utilisé.Entity Framework ObjectContext dans l'application Windows/WPF/Silverlight

Je sais que ObjectContexts doit être utilisé comme unité de travail unique. Mais alors, comment laisser les autres parties de l'application savoir que quelque chose a changé et qu'ils devraient recharger leurs données? Edit: Ok, EventAggregator, mais toutes les autres parties rechargeraient alors leurs données (probablement en grande partie en double). Aussi probablement beaucoup d'événements seraient nécessaires pour tous les types de groupes d'entités.

Comment résolvez-vous ces problèmes? Ma solution actuelle est une sorte de compromis - utilisez un ObjectContext partagé pour les données de base utilisées par l'application entière afin qu'elles puissent être partagées et mises à jour automatiquement. Et pour la grande quantité de données, utilisez un nouveau ObjectContext distinct. De meilleures idées?

Existe-t-il un moyen de "libérer" les entités de leur DataContext afin que Garbage collector puisse faire son travail et libérer la mémoire?

Répondre

2

Attendez, c'est WPF ou Silverlight? Dans ce cas, ils sont très différents et ma réponse serait différente.

WPF Solution

Dans WPF, je créerais une seule ObjectContext par formulaire. De cette façon, le contexte durera seulement aussi longtemps que la forme elle-même. Vous devez ensuite implémenter un système d'événements de sorte que lorsque vous enregistrez des modifications dans une entité, vous pouvez alerter les autres formulaires dont ils ont besoin pour actualiser leurs données (INotifyPropertyChanged, par exemple). Oren Eini wrote a pretty good article on this architecture using NHibernate in MSDN magazine. Vous devriez être en mesure d'obtenir le concept d'architecture de son article.

Solution Silverlight

Maintenant, Silverlight est différent. Silverlight vous permet essentiellement d'avoir un seul formulaire dans votre application. Oui, il y a quelques astuces que vous pouvez faire pour naviguer dans le visuel racine du formulaire vers différentes "pages" mais ce n'est toujours qu'une forme et l'utilisateur ne peut pas ouvrir plusieurs fenêtres dans un RIA Silverlight. À cause de cela, je ferais un .NET RIA Services ObjectContext par l'instance Silverlight RIA. Souvenez-vous que RIA Services n'est pas une connexion réelle à votre base de données, il s'agit simplement d'un objet de mise en cache et de suivi des modifications lié à un service Web. Ainsi, il est parfaitement acceptable de laisser cet objet en existence pendant de longues périodes car il n'entrave pas les ressources du serveur. Si votre RIA Silverlight ouvre plusieurs fenêtres de navigateur ou contient plusieurs objets Silverlight, vous devez disposer d'un objet ObjectContext par instance Silverlight.

Sur le serveur, vous utilisez un Entity Framework ObjectContext dans le service Web et il ne doit pas être actif pendant la durée d'une demande. Plus vous pouvez rendre vos services apatrides, plus ils seront évolutifs et performants. Vous voulez ouvrir votre ObjectContext EF, l'utiliser et le fermer dès que possible.


EDIT:

Si tout ce que vous êtes désireux de faire est de détacher un objet du contexte de l'objet, vous pouvez simplement utiliser la méthode context.Detach(entity). Vous pouvez trouver un example of how to do this on MSDN.

+0

Avec cette application, nous parlons de Silverlight. En utilisant Prism/Caliburn, je pense que ce n'est pas un problème d'avoir un seul ObjectContext par vue (module?). Encore une fois, le problème est que s'il y a beaucoup de données à charger au client? autant que je suis maintenant, la meilleure solution serait de créer une ObjectContext commune pour les entités de base qui sont utilisées par l'ensemble de l'application afin que ceux-ci sont automatiquement synchronisés et ObjectContexts séparés pour le chargement d'un grand groupe de données par exemple quelques rapports historiques. – gius

+0

Je n'essaierai pas d'envoyer de gros blocs de données au client. Au lieu de cela, je filtre sur le serveur et ne renvoie que les résultats que le client veut voir à ce moment-là. Les humains ne peuvent pas lire 100 000 enregistrements, alors n'en envoyez pas autant à un humain. Au lieu de cela, laissez le problème de recherche/filtre et envoyez uniquement les résultats au client. Si vous créez des rapports, créez les données récapitulatives globales sur le serveur. Par exemple, il serait préférable de calculer le volume de ventes mensuel sur le serveur et d'envoyer un seul numéro au client que de consulter 5000 fiches de ventes. –

+0

C'est vrai, mais si l'utilisateur voit à tout moment pendant la durée de vie de l'application disons les pages 1, 10, 20, ces données seront toujours dans la mémoire. D'autre part, l'utilisation d'un ObjectContext et d'une pagination de données distincts pourrait résoudre le problème de stockage de données volumineuses. – gius

1

Vous pouvez utiliser le modèle de référentiel. Une couche supplémentaire d'abstraction entre l'interface utilisateur et DAL.

Rendre les collections de données dans le référentiel statiques et observables. Ensuite, chaque fois que le référentiel met à jour l'un d'entre eux, la couche d'interface utilisateur doit se rattraper. Juste une idée.

+0

Cela ne résout pas mon problème - les collections resteraient sur le client, donc s'il y a par exemple 1 Go de données dans la base de données, tôt ou tard, il sera également chargé sur le client. D'un autre côté, cela pourrait indiquer une solution possible. Merci pour l'idée! – gius

0

Utilisez ObservableCollections dans le ObjectContext. Utilisez un événement qui se déclenche sur NotifyPropertyChange. Utilisez un modèle de publication/abonnement entre les modèles de vue pour les informer de la modification et utilisez-le pour mettre à jour les autres vues.

+1

Toutes les collections créées par l'EF sont ObservableCollection et les entités utilisent NotifyPropertyChanged. Le problème est que je ne peux pas utiliser uniquement ObjectContext pendant le cycle de vie complet de l'application, car aucune donnée ne sera libérée de la mémoire une fois chargée dans l'application. D'autre part, en utilisant ObjectContext séparé pour chaque action unique causera des problèmes dans les données rafraîchissante - les mêmes données seront chargées à plusieurs reprises de nombreux endroits et la synchronisation signifierait des événements personnalisés pour chaque type de données. La question principale est de savoir s'il existe un cadre/modèle pour ce problème. – gius

Questions connexes