Best Practices für die Verwendung des Entity Frameworks mit WPF DataBinding

entity-framework wpf

Frage

Ich bin gerade dabei, meine erste echte WPF-Anwendung zu erstellen (dh die erste, die von jemandem außer mir verwendet werden soll), und ich bin immer noch dabei, den besten Weg zu finden, um Dinge in WPF zu erledigen. Es ist eine recht einfache Datenzugriffsanwendung, die das immer noch recht neue Entity Framework verwendet, aber ich konnte im Internet keine Anleitung finden, um diese beiden Technologien (WPF und EF) gemeinsam nutzen zu können. Also dachte ich, ich würde herausfinden, wie ich mich nähere und ob jemand bessere Vorschläge hat.

  • Ich verwende das Entity Framework mit SQL Server 2008. Die EF scheint mir viel komplizierter als es sein muss und noch nicht ausgereift ist, aber Linq-to-SQL ist anscheinend tot, daher könnte ich die Technologie genauso gut verwenden dass die MS sich zu konzentrieren scheint.

  • Dies ist eine einfache Anwendung, daher habe ich es (noch) nicht gesehen, eine separate Datenschicht zu erstellen. Wenn ich auf Daten zugreifen möchte, verwende ich relativ einfache Linq-to-Entity-Abfragen, normalerweise direkt aus meinem Code-Behind, zB:

    var families = from family in entities.Family.Include("Person")
               orderby family.PrimaryLastName, family.Tag
               select family;
    
  • Linq-to-Entity-Abfragen geben ein IOrderedQueryable-Ergebnis zurück, das Änderungen in den zugrunde liegenden Daten nicht automatisch widerspiegelt. Wenn Sie zum Entitätsdatenmodell einen neuen Datensatz über Code hinzufügen, wird das Vorhandensein dieses neuen Datensatzes nicht automatisch reflektiert die verschiedenen Steuerelemente, die auf die Linq-Abfrage verweisen. Daher verwende ich die Ergebnisse dieser Abfragen in eine ObservableCollection, um die zugrunde liegenden Datenänderungen zu erfassen:

    familyOC = new ObservableCollection<Family>(families.ToList());
    
  • Dann ordne ich die ObservableCollection einer CollectionViewSource zu, damit ich filtern, sortieren usw. kann, ohne zur Datenbank zurückkehren zu müssen.

    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));
    
  • Ich binde dann die verschiedenen Steuerelemente und was nicht an diese 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" />
    
  • Wenn ich Datensätze / Objekte hinzufügen oder löschen muss, mache ich dies manuell sowohl aus dem Entitätsdatenmodell als auch aus der ObservableCollection:

    private void DeletePerson(Person person)
    {
        entities.DeleteObject(person);
        entities.SaveChanges();
        personOC.Remove(person);
    }
    
  • Im Allgemeinen verwende ich StackPanel- und DockPanel-Steuerelemente, um Elemente zu positionieren. Manchmal verwende ich ein Raster, aber es scheint schwierig zu bleiben: Wenn Sie eine neue Zeile oben in das Raster einfügen möchten, müssen Sie jedes direkt vom Raster gehostete Steuerelement berühren, um eine neue Zeile zu verwenden. Uggh. (Microsoft schien das DRY-Konzept nie wirklich zu verstehen.)

  • Ich verwende den VS WPF-Designer fast nie zum Hinzufügen, Ändern oder Positionieren von Steuerelementen. Der WPF-Designer, der mit VS geliefert wird, ist ein wenig hilfreich, um zu sehen, wie Ihr Formular aussehen wird, aber selbst dann, na ja, nicht wirklich, besonders wenn Sie Datenvorlagen verwenden, die nicht an die verfügbaren Daten gebunden sind Entwurfszeit Wenn ich mein XAML bearbeiten muss, nehme ich es wie ein Mann und mache es manuell.

  • Der größte Teil meines echten Codes ist in C # und nicht in XAML enthalten. Wie ich bereits an anderer Stelle erwähnte, abgesehen von der Tatsache, dass ich noch nicht daran gewöhnt bin, darin zu "denken", erscheint mir XAML als eine unbeholfene, hässliche Sprache, die auch schlechte Unterstützung für Designer und Intelligenz bietet kann nicht debuggt werden. Uggh. Wenn ich also klar sehen kann, wie ich etwas in C # -Code-Behind hinter mir bringen kann, das ich nicht so leicht in XAML sehen kann, dann mache ich das in C #, ohne sich zu entschuldigen. Es wurde viel darüber geschrieben, wie es am besten ist, Code-Behind fast nie auf der WPF-Seite zu verwenden (zum Beispiel für die Ereignisabwicklung), aber zumindest macht das für mich überhaupt keinen Sinn. Warum sollte ich etwas in einer hässlichen, klobigen Sprache mit gottverdächtiger Syntax, einem erstaunlich schlechten Editor und so gut wie keiner Sicherheit tun, wenn ich eine nette, saubere Sprache wie C # verwenden kann, die einen erstklassigen Editor hat, der nahezu perfekt ist Intelligenz und beispiellose Sicherheit?

Das ist also, wo ich bin. Irgendwelche Vorschläge? Vermisse ich große Teile davon? Was sollte ich wirklich darüber nachdenken, anders zu machen?

Akzeptierte Antwort

Sie müssen ein Repository-Muster implementieren, um WPF-Bedenken von EF zu trennen

Anschließend können Sie Generics verwenden, um die Komplexität der Handhabung von EF to CollectionViewSource zu reduzieren

Ein gut konzipiertes Repository sollte die Codelevel reduzieren und die Ersetzung von ORM ermöglichen (für anständige Tests erforderlich).

Hier sind einige Ideen dazu

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


Beliebte Antwort

Ich glaube auch nicht, dass Sie hier eine ToList () machen müssen. Ich glaube, ObservableCollection () braucht eine IEnumerable, welche Familien bereits sind. Wenn Sie eine ToList ausführen und diese dann an ObservableCollection übergeben, werden Sie wahrscheinlich alle Datensätze zweimal durchlaufen.

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

Versuchen Sie stattdessen Folgendes, das sollte etwas schneller sein:

familyOC = new ObservableCollection<Family>(families);


Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum