Méthodes conseillées pour utiliser Entity Framework avec WPF DataBinding

entity-framework wpf

Question

Je suis en train de créer ma première vraie application WPF (c'est-à-dire la première destinée à être utilisée par quelqu'un d'autre que moi), et je suis toujours en train de réfléchir à la meilleure façon de faire les choses dans WPF. C'est une application d'accès aux données assez simple utilisant Entity Framework, qui est encore relativement nouvelle, mais je n'ai pas trouvé beaucoup de conseils en ligne sur la meilleure façon d'utiliser ces deux technologies (WPF et EF) ensemble. Je me suis donc dit que j'allais jeter un coup d'oeil à la façon dont je l'abordais 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é qu'il ne devrait l'être et pas encore mature, mais Linq-to-SQL est apparemment mort, alors je pourrais aussi bien utiliser la technologie. que MS semble se concentrer sur.

  • C'est une application simple, donc je n'ai pas (encore) jugé bon de construire une couche de données séparée autour d'elle. Quand je veux obtenir des données, j'utilise des requêtes assez simples Linq-to-Entity, généralement directement à partir de 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 un code au modèle de données de l'entité, l'existence de ce nouvel enregistrement n'est pas automatiquement reflétée. les différentes commandes référençant la requête Linq. Par conséquent, je jette les résultats de ces requêtes dans une ObservableCollection, afin de capturer les modifications de données sous-jacentes:

    familyOC = new ObservableCollection<Family>(families.ToList());
    
  • Ensuite, je mappe l'ObservableCollection à un CollectionViewSource, afin de pouvoir filtrer, trier, etc., sans avoir à retourner à la base de données.

    familyCVS.Source = familyOC;
    familyCVS.View.Filter = new Predicate<object>(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 divers contrôles et ce qui ne l'est pas à CollectionViewSource:

    <ListBox DockPanel.Dock="Bottom" Margin="5,5,5,5" 
        Name="familyList" 
        ItemsSource="{Binding Source={StaticResource familyCVS}, Path=., Mode=TwoWay}" 
        IsSynchronizedWithCurrentItem="True" 
        ItemTemplate="{StaticResource familyTemplate}" 
        SelectionChanged="familyList_SelectionChanged" />
    
  • Lorsque j'ai besoin d'ajouter ou de supprimer des enregistrements / objets, je le fais manuellement à la fois dans le modèle de données de l'entité et dans 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, j'utilise une grille, mais cela semble difficile à maintenir: si vous souhaitez ajouter une nouvelle ligne en haut de votre grille, vous devez appuyer sur chaque contrôle directement hébergé par la grille pour lui indiquer d'utiliser une nouvelle ligne. Uggh. (Microsoft n'a jamais vraiment semblé comprendre le concept DRY.)

  • Je n’utilise presque jamais le concepteur VS WPF pour ajouter, modifier ou positionner des contrôles. Le concepteur WPF fourni avec VS est assez utile pour voir à quoi ressemblera votre formulaire, mais même dans ce cas, eh bien, pas vraiment, surtout si vous utilisez des modèles de données qui ne lient pas les données disponibles sur temps de conception. Si j'ai besoin de modifier mon XAML, je le prends comme un homme et le fais manuellement.

  • La plupart de mon vrai code est en C # plutôt qu'en XAML. Comme je l'ai mentionné ailleurs , mis à part le fait que je ne suis pas encore habitué à y "penser", XAML me semble être un langage maladroit et laid, qui arrive également avec un support médiocre de la part des concepteurs et des intellisense, et que ne peut pas être débogué. Uggh. Par conséquent, chaque fois que je vois clairement comment faire quelque chose en code C # derrière je ne peux pas voir facilement comment faire en XAML, je le fais en C #, sans excuses. Beaucoup de choses ont été écrites sur le fait que c’est une bonne pratique de ne jamais presque jamais utiliser code-behind dans la page WPF (par exemple, pour la gestion d’événements), mais pour le moment au moins, cela n’a aucun sens pour moi. Pourquoi devrais-je faire quelque chose dans un langage laid et maladroit avec une syntaxe affreuse, un éditeur incroyablement mauvais et pratiquement aucune sécurité de type, quand je peux utiliser un langage propre et agréable comme C # qui a un éditeur de classe mondiale, presque parfait IntelliSense et une sécurité de type sans précédent?

Donc c'est là où je suis. Aucune suggestion? Est-ce que je manque une grande partie de cela? Quelque chose que je devrais vraiment penser à faire différemment?

Réponse acceptée

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

Ensuite, vous pouvez utiliser des génériques pour réduire la complexité de la gestion de EF à CollectionViewSource

Un référentiel bien conçu devrait réduire les niveaux de code et permettre la substitution de tout ORM (nécessaire 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


Réponse populaire

De plus, je ne pense pas que vous ayez besoin de faire un ToList () ici. Je crois que ObservableCollection () prend un IEnumerable que les familles sont déjà. Si vous faites une liste de tâches et que vous le transmettez ensuite à ObservableCollection, je pense que vous allez parcourir tous vos enregistrements deux fois.

familyOC = new ObservableCollection<Family>(families.ToList());

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

familyOC = new ObservableCollection<Family>(families);


Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow