Best practice per l'utilizzo di Entity Framework con WPF DataBinding

entity-framework wpf

Domanda

Sono in procinto di costruire la mia prima vera applicazione WPF (cioè, la prima destinata ad essere usata da qualcuno oltre a me), e sto ancora avvolgendo la mia mente sul modo migliore di fare cose in WPF. Si tratta di un'applicazione di accesso ai dati abbastanza semplice che utilizza il Entity Framework ancora abbastanza nuovo, ma non sono stato in grado di trovare molte indicazioni online per il modo migliore di utilizzare queste due tecnologie (WPF e EF) insieme. Così ho pensato di scartare come mi sto avvicinando, e vedere se qualcuno ha suggerimenti migliori.

  • Sto utilizzando Entity Framework con SQL Server 2008. L'EF mi sembra sia molto più complicato di quanto dovrebbe essere, e non ancora maturo, ma Linq-to-SQL è apparentemente morto, quindi potrei anche usare la tecnologia su cui la MS sembra concentrarsi.

  • Questa è una semplice applicazione, quindi non ho (ancora) ritenuto opportuno creare un livello dati separato attorno ad esso. Quando voglio ottenere i dati, uso query di Linq-to-Entity abbastanza semplici, di solito direttamente dal mio code-behind, ad esempio:

    var families = from family in entities.Family.Include("Person")
               orderby family.PrimaryLastName, family.Tag
               select family;
    
  • Le query Linq-to-Entity restituiscono un risultato IOrderedQueryable, che non riflette automaticamente le modifiche nei dati sottostanti, ad esempio, se aggiungo un nuovo record tramite codice al modello di dati dell'entità, l'esistenza di questo nuovo record non si riflette automaticamente in i vari controlli che fanno riferimento alla query di Linq. Di conseguenza, sto lanciando i risultati di queste query in ObservableCollection, per acquisire le modifiche ai dati sottostanti:

    familyOC = new ObservableCollection<Family>(families.ToList());
    
  • Quindi mappo ObservableCollection a CollectionViewSource, in modo da ottenere filtri, ordinamento, ecc., Senza dover tornare al database.

    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));
    
  • Quindi leghiamo i vari controlli e what-not a quella 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" />
    
  • Quando devo aggiungere o eliminare record / oggetti, lo faccio manualmente sia dal modello di dati dell'entità, sia da ObservableCollection:

    private void DeletePerson(Person person)
    {
        entities.DeleteObject(person);
        entities.SaveChanges();
        personOC.Remove(person);
    }
    
  • In genere utilizzo i controlli StackPanel e DockPanel per posizionare gli elementi. A volte userò un Grid, ma sembra difficile da mantenere: se vuoi aggiungere una nuova riga in cima alla tua griglia, devi toccare ogni controllo direttamente ospitato dalla griglia per dirgli di usare una nuova linea. Uggh. (Microsoft non ha mai veramente avuto l'impressione di avere il concetto ASCIUTTO.)

  • Non uso quasi mai il designer VS WPF per aggiungere, modificare o posizionare i controlli. Il designer WPF che viene fornito con VS è un po 'vagamente utile per vedere come sarà la tua forma, ma anche allora, beh, non proprio, soprattutto se stai usando modelli di dati che non sono vincolanti per i dati disponibili a tempo di progettazione. Se devo modificare il mio XAML, lo prendo come un uomo e lo faccio manualmente.

  • La maggior parte del mio vero codice è in C # piuttosto che in XAML. Come ho già accennato altrove , a parte il fatto che non sono ancora abituato a "pensare" in esso, XAML mi colpisce come un linguaggio goffo e brutto, che capita anche di venire con un pessimo supporto di designer e intellisense, e che non può essere sottoposto a debug. Uggh. Di conseguenza, ogni volta che posso vedere chiaramente come fare qualcosa in C # code-behind che non riesco a vedere facilmente come farlo in XAML, lo faccio in C #, senza scuse. È stato scritto molto su come sia una buona pratica non usare quasi mai code-behind nella pagina WPF (per esempio, per la gestione degli eventi), ma almeno finora non ha senso per me. Perché dovrei fare qualcosa in un linguaggio brutto e goffo con una sintassi terribile, un editore incredibilmente cattivo, e praticamente nessun tipo di sicurezza, quando posso usare un linguaggio bello e pulito come C # che ha un editor di livello mondiale, quasi perfetto intellisense e sicurezza di tipo senza pari?

Quindi è lì che sono. Eventuali suggerimenti? Mi mancano grandi parti di questo? Qualcosa che dovrei davvero pensare di fare diversamente?

Risposta accettata

È necessario implementare un modello di repository per separare i dubbi WPF da EF

Quindi è possibile utilizzare i generici per ridurre la complessità dell'EF alla gestione di CollectionViewSource

Un repository ben progettato dovrebbe ridurre i livelli di codice e consentire a qualsiasi ORM di essere sostituito (richiesto per test decenti)

Alcune idee per questo sono qui

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


Risposta popolare

Inoltre, non penso che tu debba fare una ToList () qui. Credo che ObservableCollection () prenda un IEnumerable quali famiglie lo sono già. Se fai una ToList e poi la passa a ObservableCollection, allora penso che registrerai due volte tutti i tuoi record.

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

Invece, prova questo, che dovrebbe essere un po 'più veloce:

familyOC = new ObservableCollection<Family>(families);


Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché