Best Practices for Using Entity Framework with WPF DataBinding

I am creating my first real WPF application (i.e. the first one intended for use by someone other than me), and I'm still considering the best way to do something in WPF. This is a fairly simple data access application that uses the fairly new Entity Framework, but I have not been able to find many tutorials on the Internet to make the best use of these two technologies (WPF and EF) together. So I thought that I would throw it out as I approached him and see if anyone had any better suggestions.

  • I am using the Entity Framework with SQL Server 2008. EF hits me as much more complicated than necessary and is not yet ripe, but Linq-to-SQL seems to be dead, so I can also use the technology that seems to be focused on MS.

  • This is a simple application, so I (so far) did not consider it necessary to create a separate data layer around it. When I want to get data, I use fairly simple Linq-to-Entity queries, usually directly from my code, for example:

    var families = from family in entities.Family.Include("Person") orderby family.PrimaryLastName, family.Tag select family; 
  • Linq-to-Entity queries return an IOrderedQueryable result that does not automatically reflect changes in the underlying data, for example, if I add a new record through the code to the entity data model, the presence of this new record will not be automatically reflected in various controls that reference the Linq query . Therefore, I throw the results of these queries into the ObservableCollection to capture the main data changes:

     familyOC = new ObservableCollection<Family>(families.ToList()); 
  • Then I map the ObservableCollection to the CollectionViewSource so that I can get filtering, sorting, etc., without returning to the 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)); 
  • Then I bind the various controls and something wrong with this 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" /> 
  • When I need to add or remove records / objects, I manually do this both from the entity data model and from the ObservableCollection:

     private void DeletePerson(Person person) { entities.DeleteObject(person); entities.SaveChanges(); personOC.Remove(person); } 
  • I usually use StackPanel and DockPanel elements to position elements. Sometimes I use Grid, but it's hard for me to support: if you want to add a new row to the top of the grid, you need to touch each control directly placed in the grid to tell it to use the new row. Uggh. (Microsoft never seemed to get the DRY concept.)

  • I almost never use the VS WPF constructor to add, modify, or control positions. The WPF designer that ships with VS is somewhat vaguely useful to see how your form will look, but even then, well, actually, especially if you use data templates that are not tied to data available at design time. If I need to edit my XAML, I take it as a person and do it manually.

  • Most of my real code is in C #, not in XAML. As I mentioned elsewhere , completely eliminating the fact that I'm not used to “thinking” in it yet, XAML amazes me like a clumsy, ugly language that also happens with poor designer and intellisense support, and this can't be debugged. Uggh. Therefore, whenever I can clearly see how to do something in C # code, I cannot easily see how to do it in XAML, I do it in C # without apologizing. Much has been written about how it is good practice to almost never use code on a WPF page (say, for event processing), but at least at least it makes no sense to me. Why do I have to do something with an ugly, awkward language with awful syntax, a terribly bad editor and little security like when I can use a good, clean language like C # that has a world-class editor, almost perfectly intellisense and security an unprecedented type?

So where am I. Any suggestions? Did I miss any big parts of this? Anything I really need to think differently about?

+52
wpf entity-framework
Mar 09 '09 at 23:34
source share
6 answers

You need to implement a repository pattern to separate WPF issues from EF

Then you can use generics to reduce EF complexity to handle CollectionViewSource

A well-designed repository should reduce code levels and allow the replacement of any ORM (required for decent testing)

Some ideas for this are here.

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

+19
Mar 10 '09 at 0:35
source share

Also, I don't think you need to do ToList () here. I suppose ObservableCollection () accepts IEnumerable, which are already there. If you do a ToList and then pass that ObservableCollection, then I think you will double-check all your entries.

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

Instead, try this, which should be a little faster:

 familyOC = new ObservableCollection<Family>(families); 
+7
Mar 09 '09 at 23:55
source share

My recommendations, if possible, use Expression Blend to design your interface, instead of using Behind code and instead of using the Visual Studio designer, this will save you a lot of time. Also try rethinking the use of C # instead of xaml. Xaml is not so ugly if you make it a "WPF Way". Often, when I think it’s easier to use the code instead of xaml, this is because I am doing it wrong and I need to rethink how best to work with WPF / xaml. Xaml is great when you get used to it. I also used an entity structure that is not too large yet. I prefer NHibernate.

+4
Mar 09 '09 at 23:44
source share

I followed this link from my blog and wanted to mention something else that I found with EF. The view is off topic, but not completely.

I noticed some crazy performance issues with EF when using .Include. MS explains why, in an article on my website, I actually started porting most of my code to use the .Load method instead.

Because it is a tedious task, and because I could not find another way to do this ... I created my own method called "IncludeByRoundTrip". What it does is the path of the object and provides loading of the entire path. The end result is the same as when using, however, behind the scenes, I just call Load for all properties in the object graph.

It would be like doing something like order.Load ("Customer.Address") if such a mechanism existed. In any case, check this out on your blog and let me know your findings. I would be interested to know if others noticed a slowdown when using Include and if you have other approaches to attack the situation.

More information about my solution can be found at: http://blog.nicktown.info/2009/07/27/method-to-load-an-entire-object-graph-using-adonet-entity-framework.aspx .

Again, sorry, this was a little off topic, but I look forward to your answers.

+2
Jul 30 '09 at 1:18
source share

Another tool might be BindableLINQ

Bindable LINQ is a collection of LINQ extensions that add data binding capabilities and changes to standard LINQ queries.

+1
Mar 11 '09 at 7:10
source share



All Articles