与WPF DataBinding一起使用entity framework的最佳实践

我正在构build我的第一个真正的WPF应用程序(即,除了我之外的第一个应用程序),并且我仍然围绕在WPF中执行任务的最佳方式。 这是一个相当简单的数据访问应用程序,使用的还是相当新的entity framework,但是我一直没有find很多的在线指导,一起使用这两种技术(WPF和EF)的最佳方式。 所以我想我会抛弃我如何接近它,看看有没有人有更好的build议。

  • 我在SQL Server 2008中使用了entity framework。EF让我觉得既要复杂得多,又不成熟,但Linq-to-SQL显然已经死了,所以我不妨使用这个技术MS似乎正在关注。

  • 这是一个简单的应用程序,所以我还没有看到围绕它build立一个单独的数据层。 当我想获取数据时,我使用相当简单的Linq-to-Entity查询,通常直接从我的代码后面查询,例如:

    var families = from family in entities.Family.Include("Person") orderby family.PrimaryLastName, family.Tag select family; 
  • Linq-to-Entity查询返回一个IOrderedQueryable结果,该结果不会自动反映底层数据的变化,例如,如果通过代码向实体数据模型添加新logging,则不会自动反映此新logging的存在引用Linq查询的各种控件。 因此,我将这些查询的结果投入到ObservableCollection中,以捕获基础数据更改:

     familyOC = new ObservableCollection<Family>(families.ToList()); 
  • 然后我将ObservableCollection映射到一个CollectionViewSource,这样我就可以过滤,sorting等,而不必返回到数据库。

     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)); 
  • 然后,我绑定各种控件,而不是那个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" /> 
  • 当我需要添加或删除logging/对象时,我手动从实体数据模型和ObservableCollection这样做:

     private void DeletePerson(Person person) { entities.DeleteObject(person); entities.SaveChanges(); personOC.Remove(person); } 
  • 我通常使用StackPanel和DockPanel控件来定位元素。 有时我会使用Grid,但是看起来很难维护:如果要在网格顶部添加一个新行,您必须触摸由网格直接托pipe的每个控件,以告诉它使用一个新行。 Uggh。 (微软从来没有真正得到DRY的概念。)

  • 我几乎从不使用VS WPFdevise器来添加,修改或定位控件。 带有VS的WPFdevise器对于查看你的表单看起来有些模糊,但即使如此,也并非如此,特别是如果你使用的数据模板不能绑定到可用的数据devise时间。 如果我需要编辑我的XAML,我会像人一样手动执行。

  • 我的大部分真正的代码是用C#而不是XAML。 正如我在其他地方所提到的,除了我还没有习惯于“思考”这个事实,XAML让我觉得这是一种笨拙,丑陋的语言,也恰恰伴随着糟糕的devise和智能支持。不能被debugging。 Uggh。 因此,只要我能清楚地看到如何在C#代码隐藏中做些什么,我不能轻易地看到如何在XAML中做什么,我就用C#来做,没有任何道歉。 已经有很多关于如何在WPF页面中使用代码隐藏(比如事件处理)的良好习惯,但至less到目前为止,这对我来说是毫无意义的。 为什么我应该用一种丑陋笨重的语言来做一些事情,那就是语法错误,编辑器非常糟糕,而且几乎没有types安全性,因为我可以使用像C#这样具有世界级编辑器的干净的语言,几乎完美智能感知和无与伦比的types安全?

那就是我所在的地方 有什么build议么? 我是否错过了这个的大部分? 我真的应该考虑做什么不同的事情?

您需要实现一个存储库模式来分隔EF中的WPF问题

然后,您可以使用generics将EF的复杂性降低到CollectionViewSource处理

一个devise良好的仓库应该减less代码级别,并且可以取代任何ORM(这是体面testing所必需的)

对此的一些想法在这里

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

另外,我不认为你需要在这里做一个ToList()。 我相信ObservableCollection()需要一个已经是家族的IEnumerable。 如果你做了一个ToList,然后把它传递给ObservableCollection,那么我认为你将遍历所有的logging两次。

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

相反,试试这个应该快一点:

 familyOC = new ObservableCollection<Family>(families); 

我明白你来自哪里 Josh Smith的这篇文章帮助我改变(或者开始改变)思维模式,这样你可以从WPF中获得一些好处,而不是把它看作是一个奇怪的,阻碍的,难以debugging和不友好的框架!

我的build议是,如果可能的话,使用Expression Blend来devise界面,而不是使用Code Behind,而不是使用Visual Studiodevise器,这将为您节省大量时间。 也尝试重新思考使用C#而不是xaml。 如果你是做“WPF之路”的话,Xaml并不是那么难看。 很多时候,当我认为使用代码而不是xaml时,更容易使用代码,这是因为我做错了,需要重新考虑如何最好地使用WPF / xaml。 一旦你习惯了,Xaml就很棒。 我也使用了不太好的entity framework。 我更喜欢NHibernate。

我跟着这个链接从我的博客,并想提到一些我用EFfind的东西。 有点题外话,但不完全。

使用.Include时,我注意到了EF的一些疯狂的性能问题。 MS解释了为什么在他们的网站上的一篇文章,所以我已经开始转移我的大部分代码,而不是使用.Load方法。

因为这是一个繁琐的任务,因为我找不到另一种方式来做到这一点…我创build了自己的方法称为“IncludeByRoundTrip”。 它所做的是获取一个对象path并确保整个path被加载。 最终结果与使用include时相同,不过在幕后,我只是在对象图的所有属性上调用Load。

如果有这样一个机制存在,就会像order.Load(“Customer.Address”)一样。 无论哪种方式,请查看我的博客,让我知道你的发现。 我会好奇的看看其他人是否注意到使用“包含”的速度减慢,以及是否有其他方法来攻击这种情况。

有关我的解决scheme的更多信息: http : //blog.nicktown.info/2009/07/27/method-to-load-an-entire-object-graph-using-adonet-entity-framework.aspx 。

再一次,对不起,这有点偏离主题,但我期待着你的回应。

另一个工具可能是BindableLINQ

可绑定的LINQ是LINQ的一组扩展,它将数据绑定和传播能力添加到标准的LINQ查询中