通过WPF数据绑定使用实体框架的最佳实践

通过WPF数据绑定使用实体框架的最佳实践,wpf,entity-framework,Wpf,Entity Framework,我正在构建我的第一个真正的WPF应用程序(即,第一个打算由我以外的人使用的应用程序),我仍然在绞尽脑汁研究在WPF中做事情的最佳方法。这是一个相当简单的数据访问应用程序,使用的是仍然相当新的实体框架,但是我还没有在网上找到很多关于将这两种技术(WPF和EF)结合使用的最佳方法的指导。所以我想我应该抛开我的做法,看看是否有人有更好的建议 我将实体框架与SQLServer2008一起使用。EF给我的印象是,它比需要的复杂得多,而且还不成熟,但Linq to SQL显然已经死了,所以我不妨使用微软似

我正在构建我的第一个真正的WPF应用程序(即,第一个打算由我以外的人使用的应用程序),我仍然在绞尽脑汁研究在WPF中做事情的最佳方法。这是一个相当简单的数据访问应用程序,使用的是仍然相当新的实体框架,但是我还没有在网上找到很多关于将这两种技术(WPF和EF)结合使用的最佳方法的指导。所以我想我应该抛开我的做法,看看是否有人有更好的建议

  • 我将实体框架与SQLServer2008一起使用。EF给我的印象是,它比需要的复杂得多,而且还不成熟,但Linq to SQL显然已经死了,所以我不妨使用微软似乎关注的技术

  • 这是一个简单的应用程序,所以我(还)认为不适合围绕它构建单独的数据层。当我想要获取数据时,我使用相当简单的Linq到实体查询,通常直接从我的代码中查询,例如:

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

    familyOC = new ObservableCollection<Family>(families.ToList());
    
  • 我通常使用StackPanel和DockPanel控件来定位元素。有时我会使用网格,但似乎很难维护:如果要在网格顶部添加新行,必须触摸网格直接承载的每个控件,以告诉它使用新行。啊。(微软似乎从来没有真正接受过干涸的概念。)

  • 我几乎从不使用VSWPF设计器来添加、修改或定位控件。VS附带的WPF设计器在某种程度上有助于查看表单的外观,但即使如此,也不是真的,尤其是当您使用的数据模板没有绑定到设计时可用的数据时。如果我需要编辑我的XAML,我会像男人一样手动编辑它

  • 我的大部分真实代码都是用C#编写的,而不是用XAML编写的。正如我所提到的,除了我还不习惯用它来“思考”这个事实之外,XAML给我的印象是一种笨拙、丑陋的语言,它碰巧也有糟糕的设计器和intellisense支持,而且无法调试。啊。因此,每当我能够清楚地看到如何在C代码中完成一些在XAML中无法轻松完成的事情时,我都会在C代码中完成,而不必道歉。关于几乎从不在WPF页面中使用代码隐藏(比如,用于事件处理)是一种很好的实践,已经有很多文章写过了,但至少到目前为止,这对我来说毫无意义。当我可以使用像C#这样拥有世界级的编辑器、近乎完美的智能感知和无与伦比的类型安全性的漂亮、干净的语言时,我为什么要用一种丑陋、笨拙的语言做一些事情呢?这种语言的语法糟糕透了,编辑器糟糕透了,而且几乎没有类型安全性


这就是我的目的。有什么建议吗?我是否遗漏了其中的重要部分?我的建议是,如果可能的话,在设计界面时使用Expression Blend,而不是代码隐藏,并且不使用Visual Studio designer,这将为您节省大量时间。还可以尝试重新考虑使用C#而不是xaml。如果您采用“WPF方式”,Xaml就不会那么难看了。很多时候,当我认为使用代码隐藏而不是xaml更容易时,这是因为我用了错误的方法,需要重新思考如何最好地使用WPF/xaml。一旦你习惯了Xaml,它就很棒了。我还使用了实体框架,它还不是很好。我更喜欢NHibernate。

另外,我认为你不需要在这里做一个列表()。我相信ObservaleCollection()需要一个IEnumerable,而家族已经是这样了。如果你做一个ToList,然后把它传递给ObservableCollection,那么我认为你会在所有记录中循环两次

familyOC = new ObservableCollection<Family>(families.ToList());
familyOC=新的可观察集合(families.ToList());
相反,试试这个,应该快一点:

familyOC = new ObservableCollection<Family>(families);
familyOC=新的可观察集合(族);

您需要实现一个存储库模式,以将WPF关注点与EF分离

然后,您可以使用泛型来降低EF到CollectionViewSource处理的复杂性

一个设计良好的存储库应该降低代码级别,并使任何ORM都可以被替换(进行适当的测试所必需的)

这里有一些想法


我知道你来自哪里。这帮助我改变了(或开始改变)思维方式,这样您就可以从WPF中获得一些好处,而不是将其视为一个怪异、阻碍、难以调试和不友好的框架

另一个工具可能是


Bindable LINQ是LINQ的一组扩展,它为标准LINQ查询添加了数据绑定和更改传播功能

我从我的博客中看到了这个链接,并想提及我在EF中发现的其他内容。有点离题,但不是完全离题

在使用.Include时,我注意到EF存在一些疯狂的性能问题。MS在他们网站上的一篇文章中解释了为什么我实际上已经开始将大部分代码改为使用.Load方法

因为这是一个乏味的任务,因为我找不到另一种方法来做。。。我创建了自己的方法“IncludeByRoundTrip”。它所做的是获取对象路径并确保加载整个路径。最终结果与使用include时相同,但是在幕后,我只是对对象图中的所有属性调用Load

如果存在这样的机制,则类似于执行order.Load(“Customer.Address”)之类的操作
private void DeletePerson(Person person)
{
    entities.DeleteObject(person);
    entities.SaveChanges();
    personOC.Remove(person);
}
familyOC = new ObservableCollection<Family>(families.ToList());
familyOC = new ObservableCollection<Family>(families);