Les meilleures méthodes pour utiliser Entity Framework avec WPF DataBinding

Je suis en train de construire ma première application WPF réelle (c.-à-d. La première destinée à être utilisée par quelqu’un en dehors de moi), et je continue à me concentrer sur la meilleure façon de faire les choses dans WPF. Il s’agit d’une application d’access aux données relativement simple utilisant Entity Framework, qui est encore relativement nouveau, mais je n’ai pas été en mesure de trouver beaucoup de conseils en ligne pour utiliser au mieux ces deux technologies (WPF et EF). Alors j’ai pensé que je jetterais sur mon approche et voir si quelqu’un a de meilleures suggestions.

  • J’utilise Entity Framework avec SQL Server 2008. L’EF me semble à la fois beaucoup plus compliqué que nécessaire et pas encore mature, mais Linq-to-SQL est apparemment mort, alors autant utiliser la technologie que MS semble se concentrer sur.

  • Ceci est une application simple, donc je n’ai pas (encore) jugé bon de créer une couche de données séparée autour d’elle. Lorsque je veux obtenir des données, j’utilise des requêtes Linq-to-Entity assez simples, généralement directement depuis mon code-behind, par exemple:

    var families = from family in entities.Family.Include("Person") orderby family.PrimaryLastName, family.Tag select family; 
  • Les requêtes Linq-to-Entity renvoient un résultat IOrderedQueryable, qui ne reflète pas automatiquement les modifications des données sous-jacentes. Par exemple, si j’ajoute un nouvel enregistrement via le code au modèle de données d’entité, l’existence de ce nouvel enregistrement n’est pas automatiquement reflétée dans les différents contrôles faisant référence à la requête Linq. Par conséquent, je lance les résultats de ces requêtes dans un ObservableCollection, pour capturer les modifications de données sous-jacentes:

     familyOC = new ObservableCollection(families.ToList()); 
  • Je mappe ensuite la collection ObservableCollection sur un object CollectionViewSource, afin de pouvoir filtrer, sortinger, etc., sans avoir à retourner à la firebase database.

     familyCVS.Source = familyOC; familyCVS.View.Filter = new Predicate(ApplyFamilyFilter); familyCVS.View.SortDescriptions.Add(new System.ComponentModel.SortDescription("PrimaryLastName", System.ComponentModel.ListSortDirection.Ascending)); familyCVS.View.SortDescriptions.Add(new System.ComponentModel.SortDescription("Tag", System.ComponentModel.ListSortDirection.Ascending)); 
  • Je lie ensuite les différents contrôles et quoi – non à cette CollectionViewSource:

      
  • Lorsque je dois append ou supprimer des enregistrements / objects, je le fais manuellement à partir du modèle de données d’entité et de la classe ObservableCollection:

     private void DeletePerson(Person person) { entities.DeleteObject(person); entities.SaveChanges(); personOC.Remove(person); } 
  • J’utilise généralement les contrôles StackPanel et DockPanel pour positionner les éléments. Parfois, je vais utiliser une grid, mais cela semble difficile à gérer: si vous souhaitez append une nouvelle ligne en haut de votre grid, vous devez toucher chaque contrôle directement hébergé par la grid pour lui indiquer d’utiliser une nouvelle ligne. Uggh. (Microsoft n’a jamais vraiment semblé avoir le concept DRY.)

  • Je n’utilise presque jamais le concepteur VS WPF pour append, modifier ou positionner des contrôles. Le concepteur WPF fourni avec VS est en quelque sorte vaguement utile pour voir à quoi ressemblera votre formulaire, mais même dans ce cas, pas vraiment, surtout si vous utilisez des modèles de données qui ne sont pas liés aux données disponibles à temps de conception. Si j’ai besoin d’éditer mon XAML, je le prends comme un homme et le fais manuellement.

  • La plupart de mon vrai code est en C # plutôt que XAML. Comme je l’ai déjà mentionné ailleurs , hormis le fait que je ne suis pas encore habitué à y «penser», XAML me semble être un langage maladroit et laid, avec un mauvais support des concepteurs et des intellisense, et que ne peut pas être débogué. Uggh. Par conséquent, chaque fois que je peux voir clairement comment faire quelque chose en code C # derrière lequel je ne vois pas facilement comment faire en XAML, je le fais en C #, sans excuses. Il y a eu beaucoup d’écrits sur la façon dont il est recommandé de ne presque jamais utiliser code-behind dans la page WPF (par exemple pour la gestion des événements), mais pour le moins, cela n’a aucun sens pour moi. Pourquoi devrais-je faire quelque chose dans un langage moche et maladroit avec une syntaxe affreuse, un éditeur incroyablement mauvais et pratiquement aucun type de sécurité, lorsque je peux utiliser un langage agréable et propre comme C # avec un éditeur de classe mondiale, presque parfait IntelliSense et sécurité inégalée?

Donc c’est là que je suis. Aucune suggestion? Est-ce qu’il me manque des parties importantes? Quelque chose que je devrais vraiment penser à faire différemment?

Vous devez implémenter un modèle de référentiel pour séparer les préoccupations de WPF d’EF.

Vous pouvez ensuite utiliser des génériques pour réduire la complexité de la gestion EF à CollectionViewSource

Un référentiel bien conçu devrait réduire les niveaux de code et permettre la substitution de tout ORM (requirejs pour des tests corrects)

Quelques idées pour cela sont ici

http://blog.nicktown.info/2008/12/10/using-a-collectionviewsource-to-display-a-sorted-entitycollection.aspx

De plus, je ne pense pas que vous deviez faire une ToList () ici. Je crois que ObservableCollection () prend un IEnumerable que sont déjà les familles. Si vous faites un ToList, puis transmettez-le à ObservableCollection, alors je pense que vous parcourrez tous vos enregistrements deux fois.

 familyOC = new ObservableCollection(families.ToList()); 

Au lieu de cela, essayez ceci, ce qui devrait être un peu plus rapide:

 familyOC = new ObservableCollection(families); 

Je comprends d’où tu viens. Cet article de Josh Smith m’a aidé à changer (ou à changer) l’état d’esprit de sorte que vous puissiez bénéficier de WPF plutôt que de le voir comme un cadre étrange, obstructif, difficile à déboguer et inamical!

Mes recommandations sont, si possible, d’utiliser Expression Blend pour concevoir votre interface, au lieu de Code Behind et au lieu d’utiliser le concepteur Visual Studio, vous gagnerez beaucoup de temps. Essayez également de repenser en utilisant le C # au lieu de xaml. Xaml n’est pas si moche si vous le faites “WPF Way”. Souvent, quand je pense qu’il est plus facile d’utiliser le code derrière au lieu de xaml, c’est parce que je le fais mal et que je dois repenser la manière dont cela devrait fonctionner avec WPF / xaml. Xaml est génial quand on s’y habitue. J’ai également utilisé un framework d’entité qui n’est pas encore très bon. Je préfère NHibernate.

J’ai suivi ce lien depuis mon blog et je voulais mentionner autre chose que j’ai trouvé avec EF. Un peu hors sujet, mais pas totalement.

J’ai remarqué des problèmes de performances avec EF lors de l’utilisation de .Include. MS explique pourquoi dans un article sur leur site Web, j’ai donc commencé à déplacer la plupart de mon code pour utiliser la méthode .Load à la place.

Parce que c’est une tâche fastidieuse à faire et parce que je n’ai pas trouvé d’autre moyen de le faire … J’ai créé ma propre méthode appelée “IncludeByRoundTrip”. Ce qu’il fait est de prendre un chemin d’object et de s’assurer que le chemin complet est chargé. Le résultat final est le même que lorsque vous utilisez include mais en arrière-plan, j’appelle simplement Load sur toutes les propriétés du graphe d’object.

Cela ressemblerait à faire quelque chose comme order.Load (“Customer.Address”) si un tel mécanisme existait. Dans tous les cas, jetez un coup d’œil à mon blog et faites-moi part de vos découvertes. Je serais curieux de voir si d’autres ont remarqué des ralentissements en utilisant Include et si vous avez d’autres approches pour attaquer la situation.

Il y a plus d’informations sur ma solution sur: http://blog.nicktown.info/2009/07/27/method-to-load-an-entire-object-graph-using-adonet-entity-framework.aspx .

Encore une fois, désolé, c’était un peu hors sujet, mais j’attends vos réponses avec impatience.

Un autre outil pourrait être BindableLINQ

Bindable LINQ est un ensemble d’extensions à LINQ qui ajoute la liaison de données et modifie les capacités de propagation aux requêtes LINQ standard